karafka-core 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53d7586305360a42e124a3502563c881b87fb0d663b4520152f9c9021e1f23f4
4
- data.tar.gz: 5c0419cf6b17480694a0df8d5c3a4ce04eefa6efcd3e3d12d95417aeb04c82ea
3
+ metadata.gz: f645a5093edea0a0015987582d62b2f14deafcb18c6c9bcbbecf7dd179e93319
4
+ data.tar.gz: d8992489edd15d1d8a712dc139bdfa1259ec075429d9b1a0528954d7560c7ba8
5
5
  SHA512:
6
- metadata.gz: 88a2027bceee6b6ddba790ba6431d3883a9678524f8af3b17caead746a88b71130a55680a4cf7a95778c6556a25e093937a818d86e94916383be05fd5fff0799
7
- data.tar.gz: e860ce87d57d7e0dcae055b7c49b47d957a48125d12e00fdbcae16a2cf0732839f196fb590241ac06813b6f8a568271fa38c4feec8b7e26163b11cc99f09b015
6
+ metadata.gz: 8d8e85bd44974f9128d44e48310682c4c15b78aa1afd099c3bc511ddd159000e69fbd34a7aebb7c764c88cc642d264374ccd01a117cb077070d298560cc9a6e8
7
+ data.tar.gz: 8a8b4bd4f6d5c54372643eafb84d49ac6ae2ad2a0302e4a74ed0d27e625833d9ced7373f2815b4450a1a7996f993e8440f57ea5a580ac2a88d32848ca4af8017
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,6 +1,8 @@
1
1
  name: ci
2
2
 
3
- concurrency: ci-${{ github.ref }}
3
+ concurrency:
4
+ group: ${{ github.workflow }}-${{ github.ref }}
5
+ cancel-in-progress: true
4
6
 
5
7
  on:
6
8
  pull_request:
@@ -16,29 +18,44 @@ jobs:
16
18
  fail-fast: false
17
19
  matrix:
18
20
  ruby:
21
+ - '3.3'
19
22
  - '3.2'
20
23
  - '3.1'
21
24
  - '3.0'
22
25
  - '2.7'
23
26
  include:
24
- - ruby: '3.2'
27
+ - ruby: '3.3'
25
28
  coverage: 'true'
26
29
  steps:
27
- - uses: actions/checkout@v3
30
+ - uses: actions/checkout@v4
28
31
  - name: Install package dependencies
29
32
  run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
30
33
  - name: Set up Ruby
31
34
  uses: ruby/setup-ruby@v1
32
35
  with:
33
36
  ruby-version: ${{matrix.ruby}}
37
+ bundler: 'latest'
34
38
  - name: Install latest bundler
35
39
  run: |
36
- gem install bundler --no-document
40
+ if [[ "$(ruby -v | awk '{print $2}')" == 2.7.8* ]]; then
41
+ gem install bundler -v 2.4.22 --no-document
42
+ gem update --system 3.4.22 --no-document
43
+ else
44
+ gem install bundler --no-document
45
+ gem update --system --no-document
46
+ fi
47
+
37
48
  bundle config set without 'tools benchmarks docs'
49
+
38
50
  - name: Bundle install
39
51
  run: |
40
52
  bundle config set without development
41
- bundle install --jobs 4 --retry 3
53
+
54
+ if [[ "$(ruby -v | awk '{print $2}')" == 2.7.8* ]]; then
55
+ BUNDLER_VERSION=2.4.22 bundle install --jobs 4 --retry 3
56
+ else
57
+ bundle install --jobs 4 --retry 3
58
+ fi
42
59
  - name: Run all tests
43
60
  env:
44
61
  GITHUB_COVERAGE: ${{matrix.coverage}}
@@ -49,13 +66,13 @@ jobs:
49
66
  strategy:
50
67
  fail-fast: false
51
68
  steps:
52
- - uses: actions/checkout@v3
69
+ - uses: actions/checkout@v4
53
70
  with:
54
71
  fetch-depth: 0
55
72
  - name: Set up Ruby
56
73
  uses: ruby/setup-ruby@v1
57
74
  with:
58
- ruby-version: 3.2
75
+ ruby-version: 3.3
59
76
  - name: Install latest bundler
60
77
  run: gem install bundler --no-document
61
78
  - name: Install Diffend plugin
@@ -68,7 +85,7 @@ jobs:
68
85
  strategy:
69
86
  fail-fast: false
70
87
  steps:
71
- - uses: actions/checkout@v3
88
+ - uses: actions/checkout@v4
72
89
  with:
73
90
  fetch-depth: 0
74
91
  - name: Run Coditsu
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.3.0
data/CHANGELOG.md CHANGED
@@ -1,7 +1,38 @@
1
1
  # Karafka core changelog
2
2
 
3
+ ## 2.3.0 (2024-01-26)
4
+ - [Change] Set minimum `karafka-rdkafka` on `0.14.8` to support new features.
5
+ - [Change] Remove `concurrent-ruby` usage.
6
+
7
+ ## 2.2.7 (2023-11-07)
8
+ - [Change] Set minimum `karafka-rdkafka` on `0.13.9` to support alternative consumer builder.
9
+
10
+ ## 2.2.6 (2023-11-03)
11
+ - [Enhancement] Set backtrace for errors propagated via the errors callbacks.
12
+
13
+ ## 2.2.5 (2023-10-31)
14
+ - [Change] Drop support for Ruby 2.6 due to incompatibilities in usage of `ObjectSpace::WeakMap`
15
+ - [Change] Set minimum `karafka-rdkafka` on `0.13.8` to support consumer `#position`.
16
+
17
+ ## 2.2.4 (2023-10-25)
18
+ - [Enhancement] Allow for `lazy` evaluated constructors.
19
+ - [Enhancement] Allow no-arg constructors.
20
+
21
+ ## 2.2.3 (2023-10-17)
22
+ - [Change] Set minimum `karafka-rdkafka` on `0.13.6`.
23
+
24
+ ## 2.2.2 (2023-09-11)
25
+ - [Fix] Reuse previous frozen duration as a base for incoming computation.
26
+
27
+ ## 2.2.1 (2023-09-10)
28
+ - Optimize statistics decorator by minimizing number of new objects created.
29
+ - Expand the decoration to include new value `_fd` providing freeze duration in milliseconds. This value informs us for how many consecutive ms the given value did not change. It can be useful for detecting values that should change once in a while but are stale.
30
+
31
+ ## 2.2.0 (2023-09-01)
32
+ - [Maintenance] Update the signing cert (old expired)
33
+
3
34
  ## 2.1.1 (2023-06-28)
4
- - Set minimum `karafka-rdkafka` on `0.13.1`.
35
+ - [Change] Set minimum `karafka-rdkafka` on `0.13.1`.
5
36
 
6
37
  ## 2.1.0 (2023-06-19)
7
38
  - [Change] Set `karafka-rdkafka` requirement from `>= 0.13.0` to `<= 0.14.0`.
data/Gemfile.lock CHANGED
@@ -1,34 +1,44 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-core (2.1.1)
5
- concurrent-ruby (>= 1.1)
6
- karafka-rdkafka (>= 0.13.1, < 0.14.0)
4
+ karafka-core (2.3.0)
5
+ karafka-rdkafka (>= 0.14.8, < 0.15.0)
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
10
9
  specs:
11
- activesupport (7.0.5)
10
+ activesupport (7.1.3)
11
+ base64
12
+ bigdecimal
12
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ connection_pool (>= 2.2.5)
15
+ drb
13
16
  i18n (>= 1.6, < 2)
14
17
  minitest (>= 5.1)
18
+ mutex_m
15
19
  tzinfo (~> 2.0)
20
+ base64 (0.2.0)
21
+ bigdecimal (3.1.6)
16
22
  byebug (11.1.3)
17
- concurrent-ruby (1.2.2)
23
+ concurrent-ruby (1.2.3)
24
+ connection_pool (2.4.1)
18
25
  diff-lcs (1.5.0)
19
26
  docile (1.4.0)
20
- factory_bot (6.2.1)
27
+ drb (2.2.0)
28
+ ruby2_keywords
29
+ factory_bot (6.4.5)
21
30
  activesupport (>= 5.0.0)
22
- ffi (1.15.5)
31
+ ffi (1.16.3)
23
32
  i18n (1.14.1)
24
33
  concurrent-ruby (~> 1.0)
25
- karafka-rdkafka (0.13.2)
34
+ karafka-rdkafka (0.14.8)
26
35
  ffi (~> 1.15)
27
36
  mini_portile2 (~> 2.6)
28
37
  rake (> 12)
29
- mini_portile2 (2.8.2)
30
- minitest (5.18.0)
31
- rake (13.0.6)
38
+ mini_portile2 (2.8.5)
39
+ minitest (5.21.2)
40
+ mutex_m (0.2.0)
41
+ rake (13.1.0)
32
42
  rspec (3.12.0)
33
43
  rspec-core (~> 3.12.0)
34
44
  rspec-expectations (~> 3.12.0)
@@ -38,10 +48,11 @@ GEM
38
48
  rspec-expectations (3.12.3)
39
49
  diff-lcs (>= 1.2.0, < 2.0)
40
50
  rspec-support (~> 3.12.0)
41
- rspec-mocks (3.12.5)
51
+ rspec-mocks (3.12.6)
42
52
  diff-lcs (>= 1.2.0, < 2.0)
43
53
  rspec-support (~> 3.12.0)
44
- rspec-support (3.12.0)
54
+ rspec-support (3.12.1)
55
+ ruby2_keywords (0.0.5)
45
56
  simplecov (0.22.0)
46
57
  docile (~> 1.1)
47
58
  simplecov-html (~> 0.11)
@@ -52,6 +63,7 @@ GEM
52
63
  concurrent-ruby (~> 1.0)
53
64
 
54
65
  PLATFORMS
66
+ ruby
55
67
  x86_64-linux
56
68
 
57
69
  DEPENDENCIES
@@ -62,4 +74,4 @@ DEPENDENCIES
62
74
  simplecov
63
75
 
64
76
  BUNDLED WITH
65
- 2.4.12
77
+ 2.5.4
data/certs/cert_chain.pem CHANGED
@@ -1,26 +1,26 @@
1
1
  -----BEGIN CERTIFICATE-----
2
2
  MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQDDAdjb250
3
3
  YWN0MRcwFQYKCZImiZPyLGQBGRYHa2FyYWZrYTESMBAGCgmSJomT8ixkARkWAmlv
4
- MB4XDTIyMDgxOTE3MjEzN1oXDTIzMDgxOTE3MjEzN1owPzEQMA4GA1UEAwwHY29u
4
+ MB4XDTIzMDgyMTA3MjU1NFoXDTI0MDgyMDA3MjU1NFowPzEQMA4GA1UEAwwHY29u
5
5
  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
- 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
- jFA/GGunoPuylO/BMzy8RiQHh7VIvysAKs0tHhTx3g2D0STDpF+hcQcPELFikiT2
8
- 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
- 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
- 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
- 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
- KRMTB8gNbowJkFRJDEe8tfRy11u1fYzFg/qNO82FJd62rKAw2wN0C29yCeQOPRb1
13
- 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
- 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
- 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
- iZkwHQYDVR0RBBYwFIESY29udGFjdEBrYXJhZmthLmlvMB0GA1UdEgQWMBSBEmNv
17
- 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
- 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
- vDnJ4r7Tsb34dleqQW2zY/obG+cia3Ym2JsegXWF7dDOzCXJ4FN8MFoT2jHlqLLw
20
- yrap0YO5zx0GSQ0Dwy8h2n2v2vanMEeCx7iNm3ERgR5WuN5sjzWoz2A/JLEEcK0C
21
- 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
- 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
- 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
- Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
25
- 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
26
26
  -----END CERTIFICATE-----
data/karafka-core.gemspec CHANGED
@@ -16,10 +16,9 @@ Gem::Specification.new do |spec|
16
16
  spec.description = 'A toolset of small support modules used throughout the Karafka ecosystem'
17
17
  spec.licenses = %w[MIT]
18
18
 
19
- spec.add_dependency 'concurrent-ruby', '>= 1.1'
20
- spec.add_dependency 'karafka-rdkafka', '>= 0.13.1', '< 0.14.0'
19
+ spec.add_dependency 'karafka-rdkafka', '>= 0.14.8', '< 0.15.0'
21
20
 
22
- spec.required_ruby_version = '>= 2.6.0'
21
+ spec.required_ruby_version = '>= 2.7.0'
23
22
 
24
23
  if $PROGRAM_NAME.end_with?('gem')
25
24
  spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
@@ -32,7 +31,7 @@ Gem::Specification.new do |spec|
32
31
  spec.metadata = {
33
32
  'funding_uri' => 'https://karafka.io/#become-pro',
34
33
  'homepage_uri' => 'https://karafka.io',
35
- 'changelog_uri' => 'https://github.com/karafka/karafka-core/blob/master/CHANGELOG.md',
34
+ 'changelog_uri' => 'https://karafka.io/docs/Changelog-Karafka-Core',
36
35
  'bug_tracker_uri' => 'https://github.com/karafka/karafka-core/issues',
37
36
  'source_code_uri' => 'https://github.com/karafka/karafka-core',
38
37
  'documentation_uri' => 'https://karafka.io/docs',
@@ -4,11 +4,16 @@ module Karafka
4
4
  module Core
5
5
  module Configurable
6
6
  # Single end config value representation
7
- Leaf = Struct.new(:name, :default, :constructor, :compiled) do
7
+ Leaf = Struct.new(:name, :default, :constructor, :compiled, :lazy) do
8
8
  # @return [Boolean] true if already compiled
9
9
  def compiled?
10
10
  compiled
11
11
  end
12
+
13
+ # @return [Boolean] is this a lazy evaluated leaf
14
+ def lazy?
15
+ lazy == true
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -30,12 +30,13 @@ module Karafka
30
30
  # @param name [Symbol] setting or nested node name
31
31
  # @param default [Object] default value
32
32
  # @param constructor [#call, nil] callable or nil
33
+ # @param lazy [Boolean] is this a lazy leaf
33
34
  # @param block [Proc] block for nested settings
34
- def setting(name, default: nil, constructor: nil, &block)
35
+ def setting(name, default: nil, constructor: nil, lazy: false, &block)
35
36
  @children << if block
36
37
  Node.new(name, block)
37
38
  else
38
- Leaf.new(name, default, constructor, false)
39
+ Leaf.new(name, default, constructor, false, lazy)
39
40
  end
40
41
 
41
42
  compile
@@ -95,27 +96,75 @@ module Karafka
95
96
  @children.each do |value|
96
97
  # Do not redefine something that was already set during compilation
97
98
  # This will allow us to reconfigure things and skip override with defaults
98
- skippable = respond_to?(value.name)
99
+ skippable = respond_to?(value.name) || (value.is_a?(Leaf) && value.compiled?)
100
+ lazy_leaf = value.is_a?(Leaf) && value.lazy?
99
101
 
100
- singleton_class.attr_accessor value.name
102
+ # Do not create accessor for leafs that are lazy as they will get a custom method
103
+ # created instead
104
+ singleton_class.attr_accessor(value.name) unless lazy_leaf
101
105
 
102
106
  next if skippable
103
107
 
104
108
  initialized = if value.is_a?(Leaf)
105
- next if value.compiled?
106
-
107
109
  value.compiled = true
108
- value.constructor ? value.constructor.call(value.default) : value.default
110
+
111
+ if value.constructor && value.lazy?
112
+ false
113
+ elsif value.constructor
114
+ call_constructor(value)
115
+ else
116
+ value.default
117
+ end
109
118
  else
110
119
  value.compile
111
120
  value
112
121
  end
113
122
 
114
- public_send("#{value.name}=", initialized)
123
+ if lazy_leaf && !initialized
124
+ build_dynamic_accessor(value)
125
+ else
126
+ public_send("#{value.name}=", initialized)
127
+ end
115
128
  end
116
129
 
117
130
  @compiled = true
118
131
  end
132
+
133
+ private
134
+
135
+ # Defines a lazy evaluated read and writer that will re-evaluate in case value constructor
136
+ # evaluates to `nil` or `false`. This allows us to define dynamic constructors that
137
+ # can react to external conditions to become expected value once this value is
138
+ # available
139
+ #
140
+ # @param value [Leaf]
141
+ def build_dynamic_accessor(value)
142
+ singleton_class.attr_writer(value.name)
143
+
144
+ define_singleton_method(value.name) do
145
+ existing = instance_variable_get("@#{value.name}")
146
+
147
+ return existing if existing
148
+
149
+ built = call_constructor(value)
150
+
151
+ instance_variable_set("@#{value.name}", built)
152
+ end
153
+ end
154
+
155
+ # Runs the constructor with or without the default depending on its arity and returns the
156
+ # result
157
+ #
158
+ # @param value [Leaf]
159
+ def call_constructor(value)
160
+ constructor = value.constructor
161
+
162
+ if constructor.arity.zero?
163
+ constructor.call
164
+ else
165
+ constructor.call(value.default)
166
+ end
167
+ end
119
168
  end
120
169
  end
121
170
  end
@@ -65,14 +65,14 @@ module Karafka
65
65
 
66
66
  # Two versions are needed to pass arguments in the correct way
67
67
  if RUBY_VERSION >= '2.7'
68
- class_eval <<~CODE, __FILE__, __LINE__
68
+ class_eval <<~CODE, __FILE__, __LINE__ + 1
69
69
  # Pipes the settings setup to the config root node
70
70
  def setting(...)
71
71
  config.setting(...)
72
72
  end
73
73
  CODE
74
74
  else
75
- class_eval <<~CODE, __FILE__, __LINE__
75
+ class_eval <<~CODE, __FILE__, __LINE__ + 1
76
76
  # Pipes the settings setup to the config root node
77
77
  # @param args [Object] anything provided to settings
78
78
  # @param block [Proc] block for settings
@@ -9,7 +9,7 @@ module Karafka
9
9
  class CallbacksManager
10
10
  # @return [::Karafka::Core::Instrumentation::CallbacksManager]
11
11
  def initialize
12
- @callbacks = Concurrent::Hash.new
12
+ @callbacks = {}
13
13
  end
14
14
 
15
15
  # Invokes all the callbacks registered one after another
@@ -20,7 +20,7 @@ module Karafka
20
20
  def initialize(notifications_bus, namespace = nil)
21
21
  @notifications_bus = notifications_bus
22
22
  @namespace = namespace
23
- @mapped_events = Concurrent::Map.new
23
+ @mapped_events = {}
24
24
  end
25
25
 
26
26
  # Passes the instrumentation block (if any) into the notifications bus
@@ -22,25 +22,27 @@ module Karafka
22
22
  private_constant :EMPTY_HASH
23
23
 
24
24
  def initialize
25
- @listeners = Concurrent::Map.new do |k, v|
26
- k.compute_if_absent(v) { Concurrent::Array.new }
27
- end
28
-
25
+ @listeners = Hash.new { |hash, key| hash[key] = [] }
26
+ @mutex = Mutex.new
29
27
  # This allows us to optimize the method calling lookups
30
- @events_methods_map = Concurrent::Map.new
28
+ @events_methods_map = {}
31
29
  end
32
30
 
33
31
  # Registers a new event on which we can publish
34
32
  #
35
33
  # @param event_id [String] event id
36
34
  def register_event(event_id)
37
- @listeners[event_id]
38
- @events_methods_map[event_id] = :"on_#{event_id.to_s.tr('.', '_')}"
35
+ @mutex.synchronize do
36
+ @listeners[event_id]
37
+ @events_methods_map[event_id] = :"on_#{event_id.to_s.tr('.', '_')}"
38
+ end
39
39
  end
40
40
 
41
41
  # Clears all the subscribed listeners
42
42
  def clear
43
- @listeners.each_value(&:clear)
43
+ @mutex.synchronize do
44
+ @listeners.each_value(&:clear)
45
+ end
44
46
  end
45
47
 
46
48
  # Allows for subscription to an event
@@ -58,19 +60,21 @@ module Karafka
58
60
  # puts event
59
61
  # end
60
62
  def subscribe(event_id_or_listener, &block)
61
- if block
62
- event_id = event_id_or_listener
63
+ @mutex.synchronize do
64
+ if block
65
+ event_id = event_id_or_listener
63
66
 
64
- raise EventNotRegistered, event_id unless @listeners.key?(event_id)
67
+ raise EventNotRegistered, event_id unless @listeners.key?(event_id)
65
68
 
66
- @listeners[event_id] << block
67
- else
68
- listener = event_id_or_listener
69
+ @listeners[event_id] << block
70
+ else
71
+ listener = event_id_or_listener
69
72
 
70
- @listeners.each_key do |reg_event_id|
71
- next unless listener.respond_to?(@events_methods_map[reg_event_id])
73
+ @listeners.each_key do |reg_event_id|
74
+ next unless listener.respond_to?(@events_methods_map[reg_event_id])
72
75
 
73
- @listeners[reg_event_id] << listener
76
+ @listeners[reg_event_id] << listener
77
+ end
74
78
  end
75
79
  end
76
80
  end
@@ -8,9 +8,26 @@ module Karafka
8
8
  # instead of being a value of messages sent from the last statistics report.
9
9
  # This decorator calculates the diff against previously emited stats, so we get also
10
10
  # the diff together with the original values
11
+ #
12
+ # It adds two extra values to numerics:
13
+ # - KEY_d - delta of the previous value and current
14
+ # - KEY_fd - freeze duration - describes how long the delta remains unchanged (zero)
15
+ # and can be useful for detecting values that "hang" for extended period of time
16
+ # and do not have any change (delta always zero). This value is in ms for the
17
+ # consistency with other time operators we use.
11
18
  class StatisticsDecorator
19
+ include Helpers::Time
20
+
21
+ # Empty hash for internal referencing
22
+ EMPTY_HASH = {}.freeze
23
+
24
+ private_constant :EMPTY_HASH
25
+
12
26
  def initialize
13
- @previous = {}.freeze
27
+ @previous = EMPTY_HASH
28
+ # Operate on ms precision only
29
+ @previous_at = monotonic_now.round
30
+ @current_at = @previous_at
14
31
  end
15
32
 
16
33
  # @param emited_stats [Hash] original emited statistics
@@ -19,12 +36,17 @@ module Karafka
19
36
  # any API to get raw data, users can just assume that the result of this decoration is
20
37
  # the proper raw stats that they can use
21
38
  def call(emited_stats)
39
+ @current_at = monotonic_now.round
40
+
41
+ @change_d = @current_at - @previous_at
42
+
22
43
  diff(
23
44
  @previous,
24
45
  emited_stats
25
46
  )
26
47
 
27
48
  @previous = emited_stats
49
+ @previous_at = @current_at
28
50
 
29
51
  emited_stats.freeze
30
52
  end
@@ -39,13 +61,17 @@ module Karafka
39
61
  # @return [Object] the diff if the values were numerics or the current scope
40
62
  def diff(previous, current)
41
63
  if current.is_a?(Hash)
64
+ filled_previous = previous || EMPTY_HASH
65
+ filled_current = current || EMPTY_HASH
66
+
42
67
  # @note We cannot use #each_key as we modify the content of the current scope
43
68
  # in place (in case it's a hash)
44
69
  current.keys.each do |key|
45
70
  append(
46
- current,
71
+ filled_previous,
72
+ filled_current,
47
73
  key,
48
- diff((previous || {})[key], (current || {})[key])
74
+ diff(filled_previous[key], filled_current[key])
49
75
  )
50
76
  end
51
77
  end
@@ -62,13 +88,23 @@ module Karafka
62
88
 
63
89
  # Appends the result of the diff to a given key as long as the result is numeric
64
90
  #
91
+ # @param previous [Hash] previous scope
65
92
  # @param current [Hash] current scope
66
93
  # @param key [Symbol] key based on which we were diffing
67
94
  # @param result [Object] diff result
68
- def append(current, key, result)
95
+ def append(previous, current, key, result)
69
96
  return unless result.is_a?(Numeric)
70
97
  return if current.frozen?
71
98
 
99
+ freeze_duration_key = "#{key}_fd"
100
+
101
+ if result.zero?
102
+ current[freeze_duration_key] = previous[freeze_duration_key] || 0
103
+ current[freeze_duration_key] += @change_d
104
+ else
105
+ current[freeze_duration_key] = 0
106
+ end
107
+
72
108
  current["#{key}_d"] = result
73
109
  end
74
110
  end
@@ -30,6 +30,7 @@ module Karafka
30
30
  name = ::Rdkafka::Bindings.rd_kafka_name(client_prr)
31
31
 
32
32
  error = ::Rdkafka::RdkafkaError.new(err_code, broker_message: reason)
33
+ error.set_backtrace(caller)
33
34
 
34
35
  ::Rdkafka::Config.error_callback.call(name, error)
35
36
  end
@@ -4,6 +4,6 @@ module Karafka
4
4
  module Core
5
5
  # Current Karafka::Core version
6
6
  # We follow the versioning schema of given Karafka version
7
- VERSION = '2.1.1'
7
+ VERSION = '2.3.0'
8
8
  end
9
9
  end
data/lib/karafka-core.rb CHANGED
@@ -4,10 +4,6 @@
4
4
  yaml
5
5
  rdkafka
6
6
 
7
- concurrent/map
8
- concurrent/hash
9
- concurrent/array
10
-
11
7
  karafka/core
12
8
  karafka/core/version
13
9
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -12,65 +12,51 @@ cert_chain:
12
12
  -----BEGIN CERTIFICATE-----
13
13
  MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQDDAdjb250
14
14
  YWN0MRcwFQYKCZImiZPyLGQBGRYHa2FyYWZrYTESMBAGCgmSJomT8ixkARkWAmlv
15
- MB4XDTIyMDgxOTE3MjEzN1oXDTIzMDgxOTE3MjEzN1owPzEQMA4GA1UEAwwHY29u
15
+ MB4XDTIzMDgyMTA3MjU1NFoXDTI0MDgyMDA3MjU1NFowPzEQMA4GA1UEAwwHY29u
16
16
  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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- Cw9Y4ZwK9VFNEcV9L+3pHTHn2XfuZHtDaG198VweiF6raFO4yiEYccodH/USP0L5
25
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
37
37
  -----END CERTIFICATE-----
38
- date: 2023-06-28 00:00:00.000000000 Z
38
+ date: 2024-01-26 00:00:00.000000000 Z
39
39
  dependencies:
40
- - !ruby/object:Gem::Dependency
41
- name: concurrent-ruby
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '1.1'
47
- type: :runtime
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '1.1'
54
40
  - !ruby/object:Gem::Dependency
55
41
  name: karafka-rdkafka
56
42
  requirement: !ruby/object:Gem::Requirement
57
43
  requirements:
58
44
  - - ">="
59
45
  - !ruby/object:Gem::Version
60
- version: 0.13.1
46
+ version: 0.14.8
61
47
  - - "<"
62
48
  - !ruby/object:Gem::Version
63
- version: 0.14.0
49
+ version: 0.15.0
64
50
  type: :runtime
65
51
  prerelease: false
66
52
  version_requirements: !ruby/object:Gem::Requirement
67
53
  requirements:
68
54
  - - ">="
69
55
  - !ruby/object:Gem::Version
70
- version: 0.13.1
56
+ version: 0.14.8
71
57
  - - "<"
72
58
  - !ruby/object:Gem::Version
73
- version: 0.14.0
59
+ version: 0.15.0
74
60
  description: A toolset of small support modules used throughout the Karafka ecosystem
75
61
  email:
76
62
  - contact@karafka.io
@@ -128,7 +114,7 @@ licenses:
128
114
  metadata:
129
115
  funding_uri: https://karafka.io/#become-pro
130
116
  homepage_uri: https://karafka.io
131
- changelog_uri: https://github.com/karafka/karafka-core/blob/master/CHANGELOG.md
117
+ changelog_uri: https://karafka.io/docs/Changelog-Karafka-Core
132
118
  bug_tracker_uri: https://github.com/karafka/karafka-core/issues
133
119
  source_code_uri: https://github.com/karafka/karafka-core
134
120
  documentation_uri: https://karafka.io/docs
@@ -141,14 +127,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
127
  requirements:
142
128
  - - ">="
143
129
  - !ruby/object:Gem::Version
144
- version: 2.6.0
130
+ version: 2.7.0
145
131
  required_rubygems_version: !ruby/object:Gem::Requirement
146
132
  requirements:
147
133
  - - ">="
148
134
  - !ruby/object:Gem::Version
149
135
  version: '0'
150
136
  requirements: []
151
- rubygems_version: 3.4.10
137
+ rubygems_version: 3.5.3
152
138
  signing_key:
153
139
  specification_version: 4
154
140
  summary: Karafka ecosystem core modules
metadata.gz.sig CHANGED
Binary file