karafka-core 2.4.0 → 2.4.1.rc1

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: 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