waterdrop 2.8.0 → 2.8.1

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: 96435533f730edae9dcf7bed5426641a33715e87b55c804168fa6a02465f1431
4
- data.tar.gz: 3737e88ec3ffaa407b1cdaa523cf1d24a25aa85c4d90989a249381dbfb7a80c2
3
+ metadata.gz: 7d2fa38e1362c3069581533bd8da5ee508f00b9fea08c9a4c56ae16780c38c68
4
+ data.tar.gz: 0c861f372aeae735d0033b35bc9224e45025c03b2084d796108660b976e74eb3
5
5
  SHA512:
6
- metadata.gz: 1b83e8505ca1aa9be5c137c06af1b98e10bb8f39af93e77aefa42302bf8dc2bd95f1442eb2569d5f032e80ac0374b8013e774d1f36494d23e20af0766094e2b3
7
- data.tar.gz: 198ea59a4f7ca6a63f9816e7026c97152aaed5e6154142c47e6e96c16696a2a3d4c60cd56bf72b407b092682e9d15c08f1adfa552eb5bdc17a308f77f7424dfc
6
+ metadata.gz: 80ae3a51e3aeaa19e875eddfefb16e415b61f7ef44861d97043b060604fc9ea06d774b9e308f198d89eb813fa405f7f650e0516c8ce5688933ffce5b1b6533d8
7
+ data.tar.gz: 2da33c249c8f4e761876a18d7d95745490ed05d296a736fdf39a4ec0b84ba84f3239b8528cb91e6e08cdfe729acabda530cb464a5f8eba779373d113b5b3be94
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report an issue within the Karafka ecosystem you've discovered.
4
+ ---
5
+
6
+ To make this process smoother for everyone involved, please read the following information before filling out the template.
7
+
8
+ Scope of the OSS Support
9
+ ===========
10
+
11
+ We do not provide OSS support for outdated versions of Karafka and its components.
12
+
13
+ Please ensure that you are using a version that is still actively supported. We cannot assist with any no longer maintained versions unless you support us with our Pro offering (https://karafka.io/docs/Pro-Support/).
14
+
15
+ We acknowledge that understanding the specifics of your application and its configuration can be essential for resolving certain issues. However, due to the extensive time and resources such analysis can require, this may fall beyond our Open Source Support scope.
16
+
17
+ If Karafka or its components are critical to your infrastructure, we encourage you to consider our Pro Offering.
18
+
19
+ By backing us up, you can gain direct assistance and ensure your use case receives the dedicated attention it deserves.
20
+
21
+
22
+ Important Links to Read
23
+ ===========
24
+
25
+ Please take a moment to review the following resources before submitting your report:
26
+
27
+ - Issue Reporting Guide: https://karafka.io/docs/Support/#issue-reporting-guide
28
+ - Support Policy: https://karafka.io/docs/Support/
29
+ - Versions, Lifecycle, and EOL: https://karafka.io/docs/Versions-Lifecycle-and-EOL/
30
+
31
+
32
+ Bug Report Details
33
+ ===========
34
+
35
+ Please provide all the details per our Issue Reporting Guide: https://karafka.io/docs/Support/#issue-reporting-guide
36
+
37
+ Failing to provide the required details may result in the issue being closed. Please include all necessary information to help us understand and resolve your issue effectively.
38
+
39
+
40
+ Additional Context
41
+ ===========
42
+
43
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest new WaterDrop features or improvements to existing features.
4
+ ---
5
+
6
+ ## Is your feature request related to a problem? Please describe.
7
+
8
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9
+
10
+ ## Describe the solution you'd like
11
+
12
+ A clear and concise description of what you want to happen.
13
+
14
+ ## Describe alternatives you've considered
15
+
16
+ A clear and concise description of any alternative solutions or features you've considered.
17
+
18
+ ## Additional context
19
+
20
+ Add any other context or screenshots about the feature request here.
@@ -18,12 +18,12 @@ jobs:
18
18
  fail-fast: false
19
19
  matrix:
20
20
  ruby:
21
- - '3.4.0-preview1'
21
+ - '3.4'
22
22
  - '3.3'
23
23
  - '3.2'
24
24
  - '3.1'
25
25
  include:
26
- - ruby: '3.3'
26
+ - ruby: '3.4'
27
27
  coverage: 'true'
28
28
  steps:
29
29
  - uses: actions/checkout@v4
@@ -74,7 +74,7 @@ jobs:
74
74
  - name: Set up Ruby
75
75
  uses: ruby/setup-ruby@v1
76
76
  with:
77
- ruby-version: 3.3
77
+ ruby-version: 3.4
78
78
  - name: Install latest bundler
79
79
  run: gem install bundler --no-document
80
80
  - name: Install Diffend plugin
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.5
1
+ 3.4.1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # WaterDrop changelog
2
2
 
3
+ ## 2.8.1 (2024-12-26)
4
+ - [Enhancement] Raise `WaterDrop::ProducerNotTransactionalError` when attempting to use transactions on a non-transactional producer.
5
+ - [Fix] Disallow closing a producer from within a transaction.
6
+ - [Fix] WaterDrop should prevent opening a transaction using a closed producer.
7
+
3
8
  ## 2.8.0 (2024-09-16)
4
9
 
5
10
  This release contains **BREAKING** changes. Make sure to read and apply upgrade notes.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- waterdrop (2.8.0)
4
+ waterdrop (2.8.1)
5
5
  karafka-core (>= 2.4.3, < 3.0.0)
6
6
  karafka-rdkafka (>= 0.17.5)
7
7
  zeitwerk (~> 2.3)
@@ -42,7 +42,7 @@ GEM
42
42
  logger (1.6.1)
43
43
  mini_portile2 (2.8.7)
44
44
  minitest (5.25.1)
45
- ostruct (0.6.0)
45
+ ostruct (0.6.1)
46
46
  rake (13.2.1)
47
47
  rspec (3.13.0)
48
48
  rspec-core (~> 3.13.0)
data/docker-compose.yml CHANGED
@@ -1,9 +1,7 @@
1
- version: '2'
2
-
3
1
  services:
4
2
  kafka:
5
3
  container_name: kafka
6
- image: confluentinc/cp-kafka:7.7.1
4
+ image: confluentinc/cp-kafka:7.8.0
7
5
 
8
6
  ports:
9
7
  - 9092:9092
@@ -25,12 +25,18 @@ module WaterDrop
25
25
  # Raised when there was an attempt to use a closed producer
26
26
  ProducerClosedError = Class.new(BaseError)
27
27
 
28
+ # Raised if you attempt to close the producer from within a transaction. This is not allowed.
29
+ ProducerTransactionalCloseAttemptError = Class.new(BaseError)
30
+
28
31
  # Raised when we want to send a message that is invalid (impossible topic, etc)
29
32
  MessageInvalidError = Class.new(BaseError)
30
33
 
31
34
  # Raised when we want to commit transactional offset and the input is invalid
32
35
  TransactionalOffsetInvalidError = Class.new(BaseError)
33
36
 
37
+ # Raised when transaction attempt happens on a non-transactional producer
38
+ ProducerNotTransactionalError = Class.new(BaseError)
39
+
34
40
  # Raised when we've got an unexpected status. This should never happen. If it does, please
35
41
  # contact us as it is an error.
36
42
  StatusInvalidError = Class.new(BaseError)
@@ -55,11 +55,20 @@ module WaterDrop
55
55
  #
56
56
  # handler.wait
57
57
  def transaction
58
+ unless transactional?
59
+ raise(
60
+ Errors::ProducerNotTransactionalError,
61
+ "#{id} is not transactional"
62
+ )
63
+ end
64
+
58
65
  # This will safely allow us to support one operation transactions so a transactional
59
66
  # producer can work without the transactional block if needed
60
67
  return yield if @transaction_mutex.owned?
61
68
 
62
69
  @transaction_mutex.synchronize do
70
+ ensure_active!
71
+
63
72
  transactional_instrument(:finished) do
64
73
  with_transactional_error_handling(:begin) do
65
74
  transactional_instrument(:started) { client.begin_transaction }
@@ -85,6 +85,7 @@ module WaterDrop
85
85
 
86
86
  # Don't allow to obtain a client reference for a producer that was not configured
87
87
  raise Errors::ProducerNotConfiguredError, id if @status.initial?
88
+ raise Errors::ProducerClosedError, id if @status.closed?
88
89
 
89
90
  @connecting_mutex.synchronize do
90
91
  return @client if @client && @pid == Process.pid
@@ -180,65 +181,75 @@ module WaterDrop
180
181
  # @param force [Boolean] should we force closing even with outstanding messages after the
181
182
  # max wait timeout
182
183
  def close(force: false)
183
- @operating_mutex.synchronize do
184
- return unless @status.active?
185
-
186
- @monitor.instrument(
187
- 'producer.closed',
188
- producer_id: id
189
- ) do
190
- @status.closing!
191
- @monitor.instrument('producer.closing', producer_id: id)
192
-
193
- # No need for auto-gc if everything got closed by us
194
- # This should be used only in case a producer was not closed properly and forgotten
195
- ObjectSpace.undefine_finalizer(id)
196
-
197
- # We save this thread id because we need to bypass the activity verification on the
198
- # producer for final flush of buffers.
199
- @closing_thread_id = Thread.current.object_id
200
-
201
- # Wait until all the outgoing operations are done. Only when no one is using the
202
- # underlying client running operations we can close
203
- sleep(0.001) until @operations_in_progress.value.zero?
204
-
205
- # Flush has its own buffer mutex but even if it is blocked, flushing can still happen
206
- # as we close the client after the flushing (even if blocked by the mutex)
207
- flush(true)
208
-
209
- # We should not close the client in several threads the same time
210
- # It is safe to run it several times but not exactly the same moment
211
- # We also mark it as closed only if it was connected, if not, it would trigger a new
212
- # connection that anyhow would be immediately closed
213
- if @client
214
- # Why do we trigger it early instead of just having `#close` do it?
215
- # The linger.ms time will be ignored for the duration of the call,
216
- # queued messages will be sent to the broker as soon as possible.
217
- begin
218
- @client.flush(current_variant.max_wait_timeout) unless @client.closed?
219
- # We can safely ignore timeouts here because any left outstanding requests
220
- # will anyhow force wait on close if not forced.
221
- # If forced, we will purge the queue and just close
222
- rescue ::Rdkafka::RdkafkaError, Rdkafka::AbstractHandle::WaitTimeoutError
223
- nil
224
- ensure
225
- # Purge fully the local queue in case of a forceful shutdown just to be sure, that
226
- # there are no dangling messages. In case flush was successful, there should be
227
- # none but we do it just in case it timed out
228
- purge if force
229
- end
184
+ # If we already own the transactional mutex, it means we are inside of a transaction and
185
+ # it should not we allowed to close the producer in such a case.
186
+ if @transaction_mutex.locked? && @transaction_mutex.owned?
187
+ raise Errors::ProducerTransactionalCloseAttemptError, id
188
+ end
230
189
 
231
- @client.close
190
+ # The transactional mutex here can be used even when no transactions are in use
191
+ # It prevents us from closing a mutex during transactions and is irrelevant in other cases
192
+ @transaction_mutex.synchronize do
193
+ @operating_mutex.synchronize do
194
+ return unless @status.active?
232
195
 
233
- @client = nil
234
- end
196
+ @monitor.instrument(
197
+ 'producer.closed',
198
+ producer_id: id
199
+ ) do
200
+ @status.closing!
201
+ @monitor.instrument('producer.closing', producer_id: id)
202
+
203
+ # No need for auto-gc if everything got closed by us
204
+ # This should be used only in case a producer was not closed properly and forgotten
205
+ ObjectSpace.undefine_finalizer(id)
206
+
207
+ # We save this thread id because we need to bypass the activity verification on the
208
+ # producer for final flush of buffers.
209
+ @closing_thread_id = Thread.current.object_id
210
+
211
+ # Wait until all the outgoing operations are done. Only when no one is using the
212
+ # underlying client running operations we can close
213
+ sleep(0.001) until @operations_in_progress.value.zero?
214
+
215
+ # Flush has its own buffer mutex but even if it is blocked, flushing can still happen
216
+ # as we close the client after the flushing (even if blocked by the mutex)
217
+ flush(true)
218
+
219
+ # We should not close the client in several threads the same time
220
+ # It is safe to run it several times but not exactly the same moment
221
+ # We also mark it as closed only if it was connected, if not, it would trigger a new
222
+ # connection that anyhow would be immediately closed
223
+ if @client
224
+ # Why do we trigger it early instead of just having `#close` do it?
225
+ # The linger.ms time will be ignored for the duration of the call,
226
+ # queued messages will be sent to the broker as soon as possible.
227
+ begin
228
+ @client.flush(current_variant.max_wait_timeout) unless @client.closed?
229
+ # We can safely ignore timeouts here because any left outstanding requests
230
+ # will anyhow force wait on close if not forced.
231
+ # If forced, we will purge the queue and just close
232
+ rescue ::Rdkafka::RdkafkaError, Rdkafka::AbstractHandle::WaitTimeoutError
233
+ nil
234
+ ensure
235
+ # Purge fully the local queue in case of a forceful shutdown just to be sure, that
236
+ # there are no dangling messages. In case flush was successful, there should be
237
+ # none but we do it just in case it timed out
238
+ purge if force
239
+ end
240
+
241
+ @client.close
242
+
243
+ @client = nil
244
+ end
235
245
 
236
- # Remove callbacks runners that were registered
237
- ::Karafka::Core::Instrumentation.statistics_callbacks.delete(@id)
238
- ::Karafka::Core::Instrumentation.error_callbacks.delete(@id)
239
- ::Karafka::Core::Instrumentation.oauthbearer_token_refresh_callbacks.delete(@id)
246
+ # Remove callbacks runners that were registered
247
+ ::Karafka::Core::Instrumentation.statistics_callbacks.delete(@id)
248
+ ::Karafka::Core::Instrumentation.error_callbacks.delete(@id)
249
+ ::Karafka::Core::Instrumentation.oauthbearer_token_refresh_callbacks.delete(@id)
240
250
 
241
- @status.closed!
251
+ @status.closed!
252
+ end
242
253
  end
243
254
  end
244
255
  end
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '2.8.0'
6
+ VERSION = '2.8.1'
7
7
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterdrop
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -35,7 +34,7 @@ cert_chain:
35
34
  i9zWxov0mr44TWegTVeypcWGd/0nxu1+QHVNHJrpqlPBRvwQsUm7fwmRInGpcaB8
36
35
  ap8wNYvryYzrzvzUxIVFBVM5PacgkFqRmolCa8I7tdKQN+R1
37
36
  -----END CERTIFICATE-----
38
- date: 2024-09-16 00:00:00.000000000 Z
37
+ date: 2024-12-26 00:00:00.000000000 Z
39
38
  dependencies:
40
39
  - !ruby/object:Gem::Dependency
41
40
  name: karafka-core
@@ -95,6 +94,8 @@ files:
95
94
  - ".coditsu/ci.yml"
96
95
  - ".diffend.yml"
97
96
  - ".github/FUNDING.yml"
97
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
98
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
98
99
  - ".github/workflows/ci.yml"
99
100
  - ".gitignore"
100
101
  - ".rspec"
@@ -154,7 +155,6 @@ metadata:
154
155
  source_code_uri: https://github.com/karafka/waterdrop
155
156
  documentation_uri: https://karafka.io/docs/#waterdrop
156
157
  rubygems_mfa_required: 'true'
157
- post_install_message:
158
158
  rdoc_options: []
159
159
  require_paths:
160
160
  - lib
@@ -169,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
169
  - !ruby/object:Gem::Version
170
170
  version: '0'
171
171
  requirements: []
172
- rubygems_version: 3.5.16
173
- signing_key:
172
+ rubygems_version: 3.6.2
174
173
  specification_version: 4
175
174
  summary: Kafka messaging made easy!
176
175
  test_files: []
metadata.gz.sig CHANGED
Binary file