karafka-core 2.4.0 → 2.4.1.rc1

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: 0c68e914027164cf77e87f6f656884f09d74f5162660d312a9ecb4927ec0805f
4
- data.tar.gz: c24bbec6e2570430dfeeb0d3733a777b052b5ec6a68eacdd912751b7422940f6
3
+ metadata.gz: f3f54f6bc0338e84c7875cb5b62ca56a32f9c25d20e264fb82ee7e0d8e60b0a8
4
+ data.tar.gz: ac1ed9d339f2389d2f177c7522ce866fb6b6e291ed38d58e859c6cbe7994fcf8
5
5
  SHA512:
6
- metadata.gz: f710f79bb3da9b12cd9f830417c2eff56ad05e5bb165945c5deadb09479a2f3647b96319c2ccd40ce185886a8df727a4df63bcfc7f65cf416d811998f09b9c94
7
- data.tar.gz: ad855f6b8c600b95e573e9a5a989470785b2ce01008fa1b98211d2ae4b74bdf52baa4e1c7ceece366464bdecd7a69867311bb50a71d9e8ac46888a126f558d00
6
+ metadata.gz: 6d32caa0580cea62b988bd7966c1e6e553f192a8ab765d1cb060480e9b4d1e3494959f05cd11f4a0033110bd2b08bb6acc884c8a2baf877639ec201c2a889d80
7
+ data.tar.gz: 78422668f5de7a67c7c29504cf727ed57e9834b0aa6910959a21d733cf248e97043ba0ae854a5cfb75ff099af81da41b500f36fa2e99ac426c28fa29868979a0
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,13 @@
1
1
  # Karafka core changelog
2
2
 
3
+ ## 2.4.1 (Unreleased)
4
+ - [Enhancement] Provide fast-track for events without subscriptions to save on allocations.
5
+ - [Enhancement] Save memory allocation on each contract rule validation execution.
6
+ - [Enhancement] Save one allocation per `float_now` + 2-3x performance by using the Posix clock instead of `Time.now.utc.to_f`.
7
+ - [Enhancement] Use direct `float_millisecond` precision in `monotonic_now` not to multiply by 1000 (allocations and CPU savings).
8
+ - [Enhancement] Save one array allocation on one instrumentation.
9
+ - [Enhancement] Allow clearing one event type (dorner).
10
+
3
11
  ## 2.4.0 (2024-04-26)
4
12
  - **[Breaking]** Drop Ruby `2.7` support.
5
13
  - [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)
4
+ karafka-core (2.4.1.rc1)
5
5
  karafka-rdkafka (>= 0.15.0, < 0.16.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
@@ -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 = BasicObject.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,14 @@ 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
+ if for_checking == DIG_MISS
124
+ errors << [rule.path, :missing]
125
+ else
126
+ result = rule.validator.call(for_checking, data, errors, self)
118
127
 
119
128
  return if result == true
120
129
 
121
130
  errors << [rule.path, result || :format]
122
- else
123
- errors << [rule.path, :missing]
124
131
  end
125
132
  end
126
133
 
@@ -133,9 +140,9 @@ module Karafka
133
140
  def validate_optional(data, rule, errors)
134
141
  for_checking = dig(data, rule.path)
135
142
 
136
- return unless for_checking.first == :match
143
+ return if for_checking == DIG_MISS
137
144
 
138
- result = rule.validator.call(for_checking.last, data, errors, self)
145
+ result = rule.validator.call(for_checking, data, errors, self)
139
146
 
140
147
  return if result == true
141
148
 
@@ -156,28 +163,23 @@ module Karafka
156
163
  errors.push(*result)
157
164
  end
158
165
 
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)
166
+ # Tries to dig for a given key in a hash and returns it with indication whether or not it
167
+ # was possible to find it (dig returns nil and we don't know if it wasn't the digged key
168
+ # value)
161
169
  #
162
170
  # @param data [Hash]
163
171
  # @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
172
+ # @return [DIG_MISS, Object] found element or DIGG_MISS indicating that not found
166
173
  def dig(data, keys)
167
174
  current = data
168
- result = :match
169
175
 
170
176
  keys.each do |nesting|
171
- unless current.key?(nesting)
172
- result = :miss
173
-
174
- break
175
- end
177
+ return DIG_MISS unless current.key?(nesting)
176
178
 
177
179
  current = current[nesting]
178
180
  end
179
181
 
180
- [result, current]
182
+ current
181
183
  end
182
184
  end
183
185
  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.1.rc1'
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.1.rc1
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-17 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: karafka-rdkafka
@@ -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