karafka-core 2.4.0 → 2.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c68e914027164cf77e87f6f656884f09d74f5162660d312a9ecb4927ec0805f
4
- data.tar.gz: c24bbec6e2570430dfeeb0d3733a777b052b5ec6a68eacdd912751b7422940f6
3
+ metadata.gz: 3b5320e4ddb995e3c944e8ad2f2b31649ef455a4f9af3653c7e9c2c8bd793bec
4
+ data.tar.gz: c0817e7374a1f37c9fcd9595b78d20b83213a08676b5ec97903cccf886bead03
5
5
  SHA512:
6
- metadata.gz: f710f79bb3da9b12cd9f830417c2eff56ad05e5bb165945c5deadb09479a2f3647b96319c2ccd40ce185886a8df727a4df63bcfc7f65cf416d811998f09b9c94
7
- data.tar.gz: ad855f6b8c600b95e573e9a5a989470785b2ce01008fa1b98211d2ae4b74bdf52baa4e1c7ceece366464bdecd7a69867311bb50a71d9e8ac46888a126f558d00
6
+ metadata.gz: 922644dda424831e922a4cb3647fdb4fa598d8a79d5d01f10e11a14ab84a362a66640d4d4025de6df565f03f1a2f6537ded6b0f8d27b9c2d36bb9ba91218153d
7
+ data.tar.gz: cbcdbf0848a9a5c88e61fd3703aedd636a47ccfa6e2172f18a51f3d7d9540469730f0ac20972e2947ded1e888509523f85b87b31caa2cd76a333b713772c2111
checksums.yaml.gz.sig CHANGED
Binary file
@@ -18,6 +18,7 @@ jobs:
18
18
  fail-fast: false
19
19
  matrix:
20
20
  ruby:
21
+ - '3.4.0-preview1'
21
22
  - '3.3'
22
23
  - '3.2'
23
24
  - '3.1'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.1
1
+ 3.3.3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Karafka core changelog
2
2
 
3
+ ## 2.4.3 (2024-06-18)
4
+ - [Fix] Use `Object` instead of `BasicObject` for rule result comparison because of Time mismatch with BasicObject.
5
+
6
+ ## 2.4.2 (2024-06-17)
7
+ - [Enhancement] Allow `karafka-rdkafka` `0.16.x` to be used since API compatible.
8
+
9
+ ## 2.4.1 (2024-06-17)
10
+ - [Enhancement] Provide fast-track for events without subscriptions to save on allocations.
11
+ - [Enhancement] Save memory allocation on each contract rule validation execution.
12
+ - [Enhancement] Save one allocation per `float_now` + 2-3x performance by using the Posix clock instead of `Time.now.utc.to_f`.
13
+ - [Enhancement] Use direct `float_millisecond` precision in `monotonic_now` not to multiply by 1000 (allocations and CPU savings).
14
+ - [Enhancement] Save one array allocation on one instrumentation.
15
+ - [Enhancement] Allow clearing one event type (dorner).
16
+
3
17
  ## 2.4.0 (2024-04-26)
4
18
  - **[Breaking]** Drop Ruby `2.7` support.
5
19
  - [Enhancement] Provide necessary alterations for custom oauth token callbacks to operate.
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-core (2.4.0)
5
- karafka-rdkafka (>= 0.15.0, < 0.16.0)
4
+ karafka-core (2.4.3)
5
+ karafka-rdkafka (>= 0.15.0, < 0.17.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activesupport (7.1.3.2)
10
+ activesupport (7.1.3.4)
11
11
  base64
12
12
  bigdecimal
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
@@ -18,24 +18,25 @@ GEM
18
18
  mutex_m
19
19
  tzinfo (~> 2.0)
20
20
  base64 (0.2.0)
21
- bigdecimal (3.1.7)
21
+ bigdecimal (3.1.8)
22
22
  byebug (11.1.3)
23
- concurrent-ruby (1.2.3)
23
+ concurrent-ruby (1.3.3)
24
24
  connection_pool (2.4.1)
25
25
  diff-lcs (1.5.1)
26
26
  docile (1.4.0)
27
27
  drb (2.2.1)
28
28
  factory_bot (6.4.6)
29
29
  activesupport (>= 5.0.0)
30
- ffi (1.16.3)
31
- i18n (1.14.4)
30
+ ffi (1.17.0)
31
+ ffi (1.17.0-x86_64-linux-gnu)
32
+ i18n (1.14.5)
32
33
  concurrent-ruby (~> 1.0)
33
- karafka-rdkafka (0.15.0)
34
+ karafka-rdkafka (0.15.1)
34
35
  ffi (~> 1.15)
35
36
  mini_portile2 (~> 2.6)
36
37
  rake (> 12)
37
- mini_portile2 (2.8.6)
38
- minitest (5.22.3)
38
+ mini_portile2 (2.8.7)
39
+ minitest (5.23.1)
39
40
  mutex_m (0.2.0)
40
41
  rake (13.2.1)
41
42
  rspec (3.13.0)
@@ -44,10 +45,10 @@ GEM
44
45
  rspec-mocks (~> 3.13.0)
45
46
  rspec-core (3.13.0)
46
47
  rspec-support (~> 3.13.0)
47
- rspec-expectations (3.13.0)
48
+ rspec-expectations (3.13.1)
48
49
  diff-lcs (>= 1.2.0, < 2.0)
49
50
  rspec-support (~> 3.13.0)
50
- rspec-mocks (3.13.0)
51
+ rspec-mocks (3.13.1)
51
52
  diff-lcs (>= 1.2.0, < 2.0)
52
53
  rspec-support (~> 3.13.0)
53
54
  rspec-support (3.13.1)
@@ -72,4 +73,4 @@ DEPENDENCIES
72
73
  simplecov
73
74
 
74
75
  BUNDLED WITH
75
- 2.5.9
76
+ 2.5.13
@@ -8,3 +8,4 @@ en:
8
8
  config:
9
9
  missing: needs to be present
10
10
  id_format: needs to be a String
11
+ test_format: needs to be nil
data/karafka-core.gemspec CHANGED
@@ -16,7 +16,7 @@ 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 'karafka-rdkafka', '>= 0.15.0', '< 0.16.0'
19
+ spec.add_dependency 'karafka-rdkafka', '>= 0.15.0', '< 0.17.0'
20
20
 
21
21
  spec.required_ruby_version = '>= 3.0.0'
22
22
 
@@ -9,6 +9,13 @@ module Karafka
9
9
  class Contract
10
10
  extend Core::Configurable
11
11
 
12
+ # Constant representing a miss during dig
13
+ # We use it as a result value not to return an array with found object and a state to
14
+ # prevent additional array allocation
15
+ DIG_MISS = Object.new
16
+
17
+ private_constant :DIG_MISS
18
+
12
19
  # Yaml based error messages data
13
20
  setting(:error_messages)
14
21
 
@@ -75,7 +82,7 @@ module Karafka
75
82
  def call(data)
76
83
  errors = []
77
84
 
78
- self.class.rules.map do |rule|
85
+ self.class.rules.each do |rule|
79
86
  case rule.type
80
87
  when :required
81
88
  validate_required(data, rule, errors)
@@ -113,14 +120,16 @@ module Karafka
113
120
  def validate_required(data, rule, errors)
114
121
  for_checking = dig(data, rule.path)
115
122
 
116
- if for_checking.first == :match
117
- result = rule.validator.call(for_checking.last, data, errors, self)
123
+ # We need to compare `DIG_MISS` against stuff because of the ownership of the `#==`
124
+ # method
125
+ if DIG_MISS == for_checking
126
+ errors << [rule.path, :missing]
127
+ else
128
+ result = rule.validator.call(for_checking, data, errors, self)
118
129
 
119
130
  return if result == true
120
131
 
121
132
  errors << [rule.path, result || :format]
122
- else
123
- errors << [rule.path, :missing]
124
133
  end
125
134
  end
126
135
 
@@ -133,9 +142,9 @@ module Karafka
133
142
  def validate_optional(data, rule, errors)
134
143
  for_checking = dig(data, rule.path)
135
144
 
136
- return unless for_checking.first == :match
145
+ return if DIG_MISS == for_checking
137
146
 
138
- result = rule.validator.call(for_checking.last, data, errors, self)
147
+ result = rule.validator.call(for_checking, data, errors, self)
139
148
 
140
149
  return if result == true
141
150
 
@@ -156,28 +165,23 @@ module Karafka
156
165
  errors.push(*result)
157
166
  end
158
167
 
159
- # Tries to dig for a given key in a hash and returns it with indication whether or not it was
160
- # possible to find it (dig returns nil and we don't know if it wasn't the digged key value)
168
+ # Tries to dig for a given key in a hash and returns it with indication whether or not it
169
+ # was possible to find it (dig returns nil and we don't know if it wasn't the digged key
170
+ # value)
161
171
  #
162
172
  # @param data [Hash]
163
173
  # @param keys [Array<Symbol>]
164
- # @return [Array<Symbol, Object>] array where the first element is `:match` or `:miss` and
165
- # the digged value or nil if not found
174
+ # @return [DIG_MISS, Object] found element or DIGG_MISS indicating that not found
166
175
  def dig(data, keys)
167
176
  current = data
168
- result = :match
169
177
 
170
178
  keys.each do |nesting|
171
- unless current.key?(nesting)
172
- result = :miss
173
-
174
- break
175
- end
179
+ return DIG_MISS unless current.key?(nesting)
176
180
 
177
181
  current = current[nesting]
178
182
  end
179
183
 
180
- [result, current]
184
+ current
181
185
  end
182
186
  end
183
187
  end
@@ -6,14 +6,21 @@ module Karafka
6
6
  module Helpers
7
7
  # Time related methods used across Karafka
8
8
  module Time
9
- # @return [Float] current monotonic time in milliseconds
10
- def monotonic_now
11
- ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) * 1_000
9
+ if RUBY_VERSION >= '3.2'
10
+ # @return [Float] current monotonic time in milliseconds
11
+ def monotonic_now
12
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :float_millisecond)
13
+ end
14
+ else
15
+ # @return [Float] current monotonic time in milliseconds
16
+ def monotonic_now
17
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) * 1_000
18
+ end
12
19
  end
13
20
 
14
21
  # @return [Float] current time in float
15
22
  def float_now
16
- ::Time.now.utc.to_f
23
+ ::Process.clock_gettime(::Process::CLOCK_REALTIME)
17
24
  end
18
25
  end
19
26
  end
@@ -22,7 +22,7 @@ module Karafka
22
22
  private_constant :EMPTY_HASH
23
23
 
24
24
  def initialize
25
- @listeners = Hash.new { |hash, key| hash[key] = [] }
25
+ @listeners = {}
26
26
  @mutex = Mutex.new
27
27
  # This allows us to optimize the method calling lookups
28
28
  @events_methods_map = {}
@@ -33,15 +33,20 @@ module Karafka
33
33
  # @param event_id [String] event id
34
34
  def register_event(event_id)
35
35
  @mutex.synchronize do
36
- @listeners[event_id]
36
+ @listeners[event_id] = []
37
37
  @events_methods_map[event_id] = :"on_#{event_id.to_s.tr('.', '_')}"
38
38
  end
39
39
  end
40
40
 
41
- # Clears all the subscribed listeners
42
- def clear
41
+ # Clears all the subscribed listeners. If given an event, only clear listeners for the given
42
+ # event type.
43
+ # @param event_id [String] the key of the event to clear listeners for.
44
+ def clear(event_id = nil)
43
45
  @mutex.synchronize do
44
- @listeners.each_value(&:clear)
46
+ return @listeners.each_value(&:clear) unless event_id
47
+ return @listeners[event_id].clear if @listeners.key?(event_id)
48
+
49
+ raise(EventNotRegistered, "#{event_id} not registered!")
45
50
  end
46
51
  end
47
52
 
@@ -84,25 +89,42 @@ module Karafka
84
89
  #
85
90
  # @param event_id [String] id of the event
86
91
  # @param payload [Hash] payload for the instrumentation
87
- # @param block [Proc] instrumented code
92
+ # @yield [Proc] instrumented code
88
93
  # @return [Object] whatever the provided block (if any) returns
89
94
  #
90
95
  # @example Instrument some code
91
96
  # instrument('sleeping') do
92
97
  # sleep(1)
93
98
  # end
94
- def instrument(event_id, payload = EMPTY_HASH, &block)
95
- # Allow for instrumentation of only events we registered
96
- raise EventNotRegistered, event_id unless @listeners.key?(event_id)
97
-
98
- result, time = measure_time_taken(&block) if block_given?
99
+ def instrument(event_id, payload = EMPTY_HASH)
100
+ assigned_listeners = @listeners[event_id]
101
+
102
+ # Allow for instrumentation of only events we registered. If listeners array does not
103
+ # exist, it means the event was not registered.
104
+ raise EventNotRegistered, event_id unless assigned_listeners
105
+
106
+ if block_given?
107
+ # No point in instrumentation when no one is listening
108
+ # Since the outcome will be ignored, we may as well save on allocations
109
+ # There are many events that happen often like (`message.acknowledged`) that most
110
+ # users do not subscribe to. Such check prevents us from publishing events that would
111
+ # not be used at all saving on time measurements and objects allocations
112
+ return yield if assigned_listeners.empty?
113
+
114
+ start = monotonic_now
115
+ result = yield
116
+ time = monotonic_now - start
117
+ elsif assigned_listeners.empty?
118
+ # Skip measuring or doing anything if no one listening
119
+ return
120
+ end
99
121
 
100
122
  event = Event.new(
101
123
  event_id,
102
124
  time ? payload.merge(time: time) : payload
103
125
  )
104
126
 
105
- @listeners[event_id].each do |listener|
127
+ assigned_listeners.each do |listener|
106
128
  if listener.is_a?(Proc)
107
129
  listener.call(event)
108
130
  else
@@ -112,16 +134,6 @@ module Karafka
112
134
 
113
135
  result
114
136
  end
115
-
116
- private
117
-
118
- # Measures time taken to execute a given block and returns it together with the result of
119
- # the block execution
120
- def measure_time_taken
121
- start = monotonic_now
122
- result = yield
123
- [result, monotonic_now - start]
124
- end
125
137
  end
126
138
  end
127
139
  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.4.0'
7
+ VERSION = '2.4.3'
8
8
  end
9
9
  end
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.4.0
4
+ version: 2.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -35,7 +35,7 @@ cert_chain:
35
35
  AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
36
36
  msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
37
37
  -----END CERTIFICATE-----
38
- date: 2024-04-26 00:00:00.000000000 Z
38
+ date: 2024-06-18 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: karafka-rdkafka
@@ -46,7 +46,7 @@ dependencies:
46
46
  version: 0.15.0
47
47
  - - "<"
48
48
  - !ruby/object:Gem::Version
49
- version: 0.16.0
49
+ version: 0.17.0
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
@@ -56,7 +56,7 @@ dependencies:
56
56
  version: 0.15.0
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
- version: 0.16.0
59
+ version: 0.17.0
60
60
  description: A toolset of small support modules used throughout the Karafka ecosystem
61
61
  email:
62
62
  - contact@karafka.io
@@ -134,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
134
  - !ruby/object:Gem::Version
135
135
  version: '0'
136
136
  requirements: []
137
- rubygems_version: 3.5.9
137
+ rubygems_version: 3.5.11
138
138
  signing_key:
139
139
  specification_version: 4
140
140
  summary: Karafka ecosystem core modules
metadata.gz.sig CHANGED
Binary file