waterdrop 2.6.1.beta1 → 2.6.2

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: 5e637029ce9d9113e2d64cadcec57ac980602d489f2207507194082065604b16
4
- data.tar.gz: 21d0a5a643b3e48603fe8e8adb13dbe827a0b9b50871675e57aa62b71abe7573
3
+ metadata.gz: 1ed8c6f17cd730ab82df21e696e472c51dd51379acf757f735d43de98c00dead
4
+ data.tar.gz: 10f8b0d7bd64c26ba9b76c9edb76cf59f871cf44adbde2198907856f7b761ea4
5
5
  SHA512:
6
- metadata.gz: e34c6c5225022f191dd80da877126b5c37075b3356b1e99e4e6b79adb0c54b8939e6b43f2efded8f68a0b68424b3cdbdcaa8abe19a781456faa4f653ae9063ea
7
- data.tar.gz: 5060d94c549d5d0ac4b2e09f8ab4888643008ea732943e76f75dfedd386f08ada8a60ad278f85dcfa1172bf813c993a38b2feb71ee75ea2ce1a72bf3021edbcb
6
+ metadata.gz: a41f9a5e1ef30c69221615552f48bad03099697d27a1e405f90ab189f6c21a33dedc6382c864d4790a22d798c64023a1802597f8ce255214d077de0ebcd5028b
7
+ data.tar.gz: b21a71b53e188fd58ce8800bc23548cc3bbc0a876fe4aa8d9c67107b0e90ddfd6484c4e534137b63e4bb45d5760460ae4b7df79233d6a2acc85ba00d45a55e2a
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,9 +1,16 @@
1
1
  # WaterDrop changelog
2
2
 
3
- ### 2.6.1 (Unreleased)
3
+ ### 2.6.2 (2023-06-21)
4
+ - [Refactor] Introduce a counter-based locking approach to make sure, that we close the producer safely but at the same time not to limit messages production with producing lock.
5
+ - [Refactor] Make private methods private.
6
+ - [Refactor] Validate that producer is not closed only when attempting to produce.
7
+ - [Refactor] Improve one 5 minute long spec to run in 10 seconds.
8
+ - [Refactor] clear client assignment after closing.
9
+
10
+ ### 2.6.1 (2023-06-19)
4
11
  - [Refactor] Remove no longer needed patches.
5
12
  - [Fix] Fork detection on a short lived processes seems to fail. Clear the used parent process client reference not to close it in the finalizer (#356).
6
- - [Change] Require `karafka-rdkafka` `>= 0.13.0.beta2`.
13
+ - [Change] Require `karafka-rdkafka` `>= 0.13.0`.
7
14
  - [Change] Require 'karafka-core' `>= 2.1.0`
8
15
 
9
16
  ### 2.6.0 (2023-06-11)
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- waterdrop (2.6.1.beta1)
5
- karafka-core (>= 2.1.0.beta1, < 3.0.0)
4
+ waterdrop (2.6.2)
5
+ karafka-core (>= 2.1.0, < 3.0.0)
6
6
  zeitwerk (~> 2.3)
7
7
 
8
8
  GEM
@@ -22,10 +22,10 @@ GEM
22
22
  ffi (1.15.5)
23
23
  i18n (1.14.1)
24
24
  concurrent-ruby (~> 1.0)
25
- karafka-core (2.1.0.beta1)
25
+ karafka-core (2.1.0)
26
26
  concurrent-ruby (>= 1.1)
27
- karafka-rdkafka (>= 0.13.0.beta2, < 0.14.0)
28
- karafka-rdkafka (0.13.0.beta2)
27
+ karafka-rdkafka (>= 0.13.0, < 0.14.0)
28
+ karafka-rdkafka (0.13.0)
29
29
  ffi (~> 1.15)
30
30
  mini_portile2 (~> 2.6)
31
31
  rake (> 12)
@@ -24,8 +24,8 @@ module WaterDrop
24
24
  # "Produces" message to Kafka: it acknowledges it locally, adds it to the internal buffer
25
25
  # @param message [Hash] `WaterDrop::Producer#produce_sync` message hash
26
26
  def produce(message)
27
- topic = message.fetch(:topic) { raise ArgumentError, ':topic is missing' }
28
- @topics[topic] << message
27
+ # We pre-validate the message payload, so topic is ensured to be present
28
+ @topics[message.fetch(:topic)] << message
29
29
  @messages << message
30
30
  SyncResponse.new
31
31
  end
@@ -14,8 +14,6 @@ module WaterDrop
14
14
  # @raise [Errors::MessageInvalidError] When provided message details are invalid and the
15
15
  # message could not be sent to Kafka
16
16
  def produce_async(message)
17
- ensure_active!
18
-
19
17
  message = middleware.run(message)
20
18
  validate_message!(message)
21
19
 
@@ -49,8 +47,6 @@ module WaterDrop
49
47
  # @raise [Errors::MessageInvalidError] When any of the provided messages details are invalid
50
48
  # and the message could not be sent to Kafka
51
49
  def produce_many_async(messages)
52
- ensure_active!
53
-
54
50
  dispatched = []
55
51
  messages = middleware.run_many(messages)
56
52
  messages.each { |message| validate_message!(message) }
@@ -11,6 +11,7 @@ module WaterDrop
11
11
  # message could not be sent to Kafka
12
12
  def buffer(message)
13
13
  ensure_active!
14
+
14
15
  message = middleware.run(message)
15
16
  validate_message!(message)
16
17
 
@@ -49,8 +50,6 @@ module WaterDrop
49
50
  # @return [Array<Rdkafka::Producer::DeliveryHandle>] delivery handles for messages that were
50
51
  # flushed
51
52
  def flush_async
52
- ensure_active!
53
-
54
53
  @monitor.instrument(
55
54
  'buffer.flushed_async',
56
55
  producer_id: id,
@@ -62,8 +61,6 @@ module WaterDrop
62
61
  # @return [Array<Rdkafka::Producer::DeliveryReport>] delivery reports for messages that were
63
62
  # flushed
64
63
  def flush_sync
65
- ensure_active!
66
-
67
64
  @monitor.instrument(
68
65
  'buffer.flushed_sync',
69
66
  producer_id: id,
@@ -16,8 +16,6 @@ module WaterDrop
16
16
  # @raise [Errors::MessageInvalidError] When provided message details are invalid and the
17
17
  # message could not be sent to Kafka
18
18
  def produce_sync(message)
19
- ensure_active!
20
-
21
19
  message = middleware.run(message)
22
20
  validate_message!(message)
23
21
 
@@ -55,8 +53,6 @@ module WaterDrop
55
53
  # @raise [Errors::MessageInvalidError] When any of the provided messages details are invalid
56
54
  # and the message could not be sent to Kafka
57
55
  def produce_many_sync(messages)
58
- ensure_active! unless @closing_thread_id && @closing_thread_id == Thread.current.object_id
59
-
60
56
  messages = middleware.run_many(messages)
61
57
  messages.each { |message| validate_message!(message) }
62
58
 
@@ -34,9 +34,10 @@ module WaterDrop
34
34
  # @param block [Proc] configuration block
35
35
  # @return [Producer] producer instance
36
36
  def initialize(&block)
37
+ @operations_in_progress = 0
37
38
  @buffer_mutex = Mutex.new
38
39
  @connecting_mutex = Mutex.new
39
- @closing_mutex = Mutex.new
40
+ @operating_mutex = Mutex.new
40
41
 
41
42
  @status = Status.new
42
43
  @messages = Concurrent::Array.new
@@ -118,7 +119,7 @@ module WaterDrop
118
119
 
119
120
  # Flushes the buffers in a sync way and closes the producer
120
121
  def close
121
- @closing_mutex.synchronize do
122
+ @operating_mutex.synchronize do
122
123
  return unless @status.active?
123
124
 
124
125
  @monitor.instrument(
@@ -135,6 +136,10 @@ module WaterDrop
135
136
  # producer for final flush of buffers.
136
137
  @closing_thread_id = Thread.current.object_id
137
138
 
139
+ # Wait until all the outgoing operations are done. Only when no one is using the
140
+ # underlying client running operations we can close
141
+ sleep(0.001) until @operations_in_progress.zero?
142
+
138
143
  # Flush has its own buffer mutex but even if it is blocked, flushing can still happen
139
144
  # as we close the client after the flushing (even if blocked by the mutex)
140
145
  flush(true)
@@ -143,7 +148,10 @@ module WaterDrop
143
148
  # It is safe to run it several times but not exactly the same moment
144
149
  # We also mark it as closed only if it was connected, if not, it would trigger a new
145
150
  # connection that anyhow would be immediately closed
146
- client.close if @client
151
+ if @client
152
+ client.close
153
+ @client = nil
154
+ end
147
155
 
148
156
  # Remove callbacks runners that were registered
149
157
  ::Karafka::Core::Instrumentation.statistics_callbacks.delete(@id)
@@ -154,13 +162,17 @@ module WaterDrop
154
162
  end
155
163
  end
156
164
 
165
+ private
166
+
157
167
  # Ensures that we don't run any operations when the producer is not configured or when it
158
168
  # was already closed
159
169
  def ensure_active!
160
170
  return if @status.active?
171
+ return if @status.closing? && @operating_mutex.owned?
161
172
 
162
173
  raise Errors::ProducerNotConfiguredError, id if @status.initial?
163
- raise Errors::ProducerClosedError, id if @status.closing? || @status.closed?
174
+ raise Errors::ProducerClosedError, id if @status.closing?
175
+ raise Errors::ProducerClosedError, id if @status.closed?
164
176
 
165
177
  # This should never happen
166
178
  raise Errors::StatusInvalidError, [id, @status.to_s]
@@ -184,14 +196,21 @@ module WaterDrop
184
196
  )
185
197
  end
186
198
 
187
- private
188
-
189
199
  # Runs the client produce method with a given message
190
200
  #
191
201
  # @param message [Hash] message we want to send
192
202
  def produce(message)
193
203
  produce_time ||= monotonic_now
194
204
 
205
+ # This can happen only during flushing on closing, in case like this we don't have to
206
+ # synchronize because we already own the lock
207
+ if @operating_mutex.owned?
208
+ @operations_in_progress += 1
209
+ else
210
+ @operating_mutex.synchronize { @operations_in_progress += 1 }
211
+ ensure_active!
212
+ end
213
+
195
214
  client.produce(**message)
196
215
  rescue SUPPORTED_FLOW_ERRORS.first => e
197
216
  # Unless we want to wait and retry and it's a full queue, we raise normally
@@ -229,7 +248,10 @@ module WaterDrop
229
248
  sleep @config.wait_backoff_on_queue_full
230
249
  end
231
250
 
251
+ @operations_in_progress -= 1
232
252
  retry
253
+ ensure
254
+ @operations_in_progress -= 1
233
255
  end
234
256
  end
235
257
  end
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '2.6.1.beta1'
6
+ VERSION = '2.6.2'
7
7
  end
data/waterdrop.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.description = spec.summary
17
17
  spec.license = 'MIT'
18
18
 
19
- spec.add_dependency 'karafka-core', '>= 2.1.0.beta1', '< 3.0.0'
19
+ spec.add_dependency 'karafka-core', '>= 2.1.0', '< 3.0.0'
20
20
  spec.add_dependency 'zeitwerk', '~> 2.3'
21
21
 
22
22
  if $PROGRAM_NAME.end_with?('gem')
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterdrop
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.1.beta1
4
+ version: 2.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -35,7 +35,7 @@ cert_chain:
35
35
  Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
36
36
  MGU0FeSV2Yj7Xc2x/7BzLK8xQn5l7Yy75iPF+KP3vVmDHnNl
37
37
  -----END CERTIFICATE-----
38
- date: 2023-06-17 00:00:00.000000000 Z
38
+ date: 2023-06-21 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: karafka-core
@@ -43,7 +43,7 @@ dependencies:
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 2.1.0.beta1
46
+ version: 2.1.0
47
47
  - - "<"
48
48
  - !ruby/object:Gem::Version
49
49
  version: 3.0.0
@@ -53,7 +53,7 @@ dependencies:
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: 2.1.0.beta1
56
+ version: 2.1.0
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
59
  version: 3.0.0
@@ -144,9 +144,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
144
  version: '0'
145
145
  required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  requirements:
147
- - - ">"
147
+ - - ">="
148
148
  - !ruby/object:Gem::Version
149
- version: 1.3.1
149
+ version: '0'
150
150
  requirements: []
151
151
  rubygems_version: 3.4.10
152
152
  signing_key:
metadata.gz.sig CHANGED
@@ -1 +1 @@
1
- Z9}O��Tg+��zvQ7w����jh%/4A�Ѱc�)�0A��)��u~�.]�!S�
1
+ E���y���!+t �V� ����5cK|��3��=�$š�x�3KN$ R<�T���=�{60�-�V����=���6���w�}�Ff%rZ��������sP��X��)�]��