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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ci.yml +3 -3
- data/.ruby-version +1 -1
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +2 -2
- data/docker-compose.yml +1 -3
- data/lib/waterdrop/errors.rb +6 -0
- data/lib/waterdrop/producer/transactions.rb +9 -0
- data/lib/waterdrop/producer.rb +66 -55
- data/lib/waterdrop/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +5 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d2fa38e1362c3069581533bd8da5ee508f00b9fea08c9a4c56ae16780c38c68
|
4
|
+
data.tar.gz: 0c861f372aeae735d0033b35bc9224e45025c03b2084d796108660b976e74eb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/.github/workflows/ci.yml
CHANGED
@@ -18,12 +18,12 @@ jobs:
|
|
18
18
|
fail-fast: false
|
19
19
|
matrix:
|
20
20
|
ruby:
|
21
|
-
- '3.4
|
21
|
+
- '3.4'
|
22
22
|
- '3.3'
|
23
23
|
- '3.2'
|
24
24
|
- '3.1'
|
25
25
|
include:
|
26
|
-
- ruby: '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.
|
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.
|
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.
|
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.
|
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
data/lib/waterdrop/errors.rb
CHANGED
@@ -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 }
|
data/lib/waterdrop/producer.rb
CHANGED
@@ -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
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
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
|
-
|
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
|
-
|
234
|
-
|
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
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
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
|
-
|
251
|
+
@status.closed!
|
252
|
+
end
|
242
253
|
end
|
243
254
|
end
|
244
255
|
end
|
data/lib/waterdrop/version.rb
CHANGED
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.
|
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-
|
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.
|
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
|