waterdrop 2.6.0 → 2.6.1.beta1
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/CHANGELOG.md +7 -1
- data/Gemfile.lock +11 -12
- data/README.md +6 -0
- data/lib/waterdrop/producer.rb +10 -5
- data/lib/waterdrop/version.rb +1 -1
- data/waterdrop.gemspec +1 -1
- data.tar.gz.sig +0 -0
- metadata +6 -9
- metadata.gz.sig +1 -2
- data/lib/waterdrop/patches/rdkafka/client.rb +0 -34
- data/lib/waterdrop/patches/rdkafka/metadata.rb +0 -45
- data/lib/waterdrop/patches/rdkafka/producer.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e637029ce9d9113e2d64cadcec57ac980602d489f2207507194082065604b16
|
4
|
+
data.tar.gz: 21d0a5a643b3e48603fe8e8adb13dbe827a0b9b50871675e57aa62b71abe7573
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e34c6c5225022f191dd80da877126b5c37075b3356b1e99e4e6b79adb0c54b8939e6b43f2efded8f68a0b68424b3cdbdcaa8abe19a781456faa4f653ae9063ea
|
7
|
+
data.tar.gz: 5060d94c549d5d0ac4b2e09f8ab4888643008ea732943e76f75dfedd386f08ada8a60ad278f85dcfa1172bf813c993a38b2feb71ee75ea2ce1a72bf3021edbcb
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
# WaterDrop changelog
|
2
2
|
|
3
|
+
### 2.6.1 (Unreleased)
|
4
|
+
- [Refactor] Remove no longer needed patches.
|
5
|
+
- [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`.
|
7
|
+
- [Change] Require 'karafka-core' `>= 2.1.0`
|
8
|
+
|
3
9
|
### 2.6.0 (2023-06-11)
|
4
10
|
- [Improvement] Introduce `client_class` setting for ability to replace underlying client with anything specific to a given env (dev, test, etc).
|
5
11
|
- [Improvement] Introduce `Clients::Buffered` useful for writing specs that do not have to talk with Kafka (id-ilych)
|
6
12
|
- [Improvement] Make `#produce` method private to avoid confusion and make sure it is not used directly (it is not part of the official API).
|
7
13
|
- [Change] Change `wait_on_queue_full` from `false` to `true` as a default.
|
8
14
|
- [Change] Rename `wait_on_queue_full_timeout` to `wait_backoff_on_queue_full` to match what it actually does.
|
9
|
-
- [Enhancement] Introduce `wait_timeout_on_queue_full` with proper meaning. That is, this represents time after which despite backoff the error will be raised. This should allow to raise an error in case the backoff attempts were insufficient. This prevents from a case, where upon never deliverable messages we would end up with an
|
15
|
+
- [Enhancement] Introduce `wait_timeout_on_queue_full` with proper meaning. That is, this represents time after which despite backoff the error will be raised. This should allow to raise an error in case the backoff attempts were insufficient. This prevents from a case, where upon never deliverable messages we would end up with an infinite loop.
|
10
16
|
- [Fix] Provide `type` for queue full errors that references the appropriate public API method correctly.
|
11
17
|
|
12
18
|
### Upgrade notes
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
waterdrop (2.6.
|
5
|
-
karafka-core (>= 2.0.
|
4
|
+
waterdrop (2.6.1.beta1)
|
5
|
+
karafka-core (>= 2.1.0.beta1, < 3.0.0)
|
6
6
|
zeitwerk (~> 2.3)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (7.0.
|
11
|
+
activesupport (7.0.5)
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
13
|
i18n (>= 1.6, < 2)
|
14
14
|
minitest (>= 5.1)
|
@@ -20,25 +20,25 @@ GEM
|
|
20
20
|
factory_bot (6.2.1)
|
21
21
|
activesupport (>= 5.0.0)
|
22
22
|
ffi (1.15.5)
|
23
|
-
i18n (1.
|
23
|
+
i18n (1.14.1)
|
24
24
|
concurrent-ruby (~> 1.0)
|
25
|
-
karafka-core (2.0.
|
25
|
+
karafka-core (2.1.0.beta1)
|
26
26
|
concurrent-ruby (>= 1.1)
|
27
|
-
karafka-rdkafka (>= 0.
|
28
|
-
karafka-rdkafka (0.
|
27
|
+
karafka-rdkafka (>= 0.13.0.beta2, < 0.14.0)
|
28
|
+
karafka-rdkafka (0.13.0.beta2)
|
29
29
|
ffi (~> 1.15)
|
30
30
|
mini_portile2 (~> 2.6)
|
31
31
|
rake (> 12)
|
32
|
-
mini_portile2 (2.8.
|
32
|
+
mini_portile2 (2.8.2)
|
33
33
|
minitest (5.18.0)
|
34
34
|
rake (13.0.6)
|
35
35
|
rspec (3.12.0)
|
36
36
|
rspec-core (~> 3.12.0)
|
37
37
|
rspec-expectations (~> 3.12.0)
|
38
38
|
rspec-mocks (~> 3.12.0)
|
39
|
-
rspec-core (3.12.
|
39
|
+
rspec-core (3.12.2)
|
40
40
|
rspec-support (~> 3.12.0)
|
41
|
-
rspec-expectations (3.12.
|
41
|
+
rspec-expectations (3.12.3)
|
42
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
43
43
|
rspec-support (~> 3.12.0)
|
44
44
|
rspec-mocks (3.12.5)
|
@@ -53,10 +53,9 @@ GEM
|
|
53
53
|
simplecov_json_formatter (0.1.4)
|
54
54
|
tzinfo (2.0.6)
|
55
55
|
concurrent-ruby (~> 1.0)
|
56
|
-
zeitwerk (2.6.
|
56
|
+
zeitwerk (2.6.8)
|
57
57
|
|
58
58
|
PLATFORMS
|
59
|
-
arm64-darwin-21
|
60
59
|
x86_64-linux
|
61
60
|
|
62
61
|
DEPENDENCIES
|
data/README.md
CHANGED
@@ -333,6 +333,12 @@ producer.close
|
|
333
333
|
|
334
334
|
See the `WaterDrop::Instrumentation::Notifications::EVENTS` for the list of all the supported events.
|
335
335
|
|
336
|
+
### Karafka Web-UI
|
337
|
+
|
338
|
+
Karafka [Web UI](https://karafka.io/docs/Web-UI-Getting-Started/) is a user interface for the Karafka framework. The Web UI provides a convenient way for monitor all producers related errors out of the box.
|
339
|
+
|
340
|
+
![Example producer errors in Karafka Web-UI](https://raw.githubusercontent.com/karafka/misc/master/printscreens/web-ui/errors-producer.png)
|
341
|
+
|
336
342
|
### Usage statistics
|
337
343
|
|
338
344
|
WaterDrop is configured to emit internal `librdkafka` metrics every five seconds. You can change this by setting the `kafka` `statistics.interval.ms` configuration property to a value greater of equal `0`. Emitted statistics are available after subscribing to the `statistics.emitted` publisher event. If set to `0`, metrics will not be published.
|
data/lib/waterdrop/producer.rb
CHANGED
@@ -76,13 +76,18 @@ module WaterDrop
|
|
76
76
|
@connecting_mutex.synchronize do
|
77
77
|
return @client if @client && @pid == Process.pid
|
78
78
|
|
79
|
-
# We should raise an error when trying to use a producer from a fork, that is already
|
80
|
-
# connected to Kafka. We allow forking producers only before they are used
|
81
|
-
raise Errors::ProducerUsedInParentProcess, Process.pid if @status.connected?
|
82
|
-
|
83
79
|
# We undefine all the finalizers, in case it was a fork, so the finalizers from the parent
|
84
80
|
# process don't leak
|
85
81
|
ObjectSpace.undefine_finalizer(id)
|
82
|
+
|
83
|
+
# We should raise an error when trying to use a producer with client from a fork. Always.
|
84
|
+
if @client
|
85
|
+
# We need to reset the client, otherwise there might be attempt to close the parent
|
86
|
+
# client
|
87
|
+
@client = nil
|
88
|
+
raise Errors::ProducerUsedInParentProcess, Process.pid
|
89
|
+
end
|
90
|
+
|
86
91
|
# Finalizer tracking is needed for handling shutdowns gracefully.
|
87
92
|
# I don't expect everyone to remember about closing all the producers all the time, thus
|
88
93
|
# this approach is better. Although it is still worth keeping in mind, that this will
|
@@ -138,7 +143,7 @@ module WaterDrop
|
|
138
143
|
# It is safe to run it several times but not exactly the same moment
|
139
144
|
# We also mark it as closed only if it was connected, if not, it would trigger a new
|
140
145
|
# connection that anyhow would be immediately closed
|
141
|
-
client.close
|
146
|
+
client.close if @client
|
142
147
|
|
143
148
|
# Remove callbacks runners that were registered
|
144
149
|
::Karafka::Core::Instrumentation.statistics_callbacks.delete(@id)
|
data/lib/waterdrop/version.rb
CHANGED
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.0.
|
19
|
+
spec.add_dependency 'karafka-core', '>= 2.1.0.beta1', '< 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.
|
4
|
+
version: 2.6.1.beta1
|
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-
|
38
|
+
date: 2023-06-17 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.0.
|
46
|
+
version: 2.1.0.beta1
|
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.0.
|
56
|
+
version: 2.1.0.beta1
|
57
57
|
- - "<"
|
58
58
|
- !ruby/object:Gem::Version
|
59
59
|
version: 3.0.0
|
@@ -112,9 +112,6 @@ files:
|
|
112
112
|
- lib/waterdrop/instrumentation/vendors/datadog/dashboard.json
|
113
113
|
- lib/waterdrop/instrumentation/vendors/datadog/metrics_listener.rb
|
114
114
|
- lib/waterdrop/middleware.rb
|
115
|
-
- lib/waterdrop/patches/rdkafka/client.rb
|
116
|
-
- lib/waterdrop/patches/rdkafka/metadata.rb
|
117
|
-
- lib/waterdrop/patches/rdkafka/producer.rb
|
118
115
|
- lib/waterdrop/producer.rb
|
119
116
|
- lib/waterdrop/producer/async.rb
|
120
117
|
- lib/waterdrop/producer/buffer.rb
|
@@ -147,9 +144,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
144
|
version: '0'
|
148
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
146
|
requirements:
|
150
|
-
- - "
|
147
|
+
- - ">"
|
151
148
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
149
|
+
version: 1.3.1
|
153
150
|
requirements: []
|
154
151
|
rubygems_version: 3.4.10
|
155
152
|
signing_key:
|
metadata.gz.sig
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
ٹ��@��l�.K��Z�2��'�#�1V)�J8�B;�˲�XsIx���~�{�])����$�-v���_�gԖd}���MM>�5lF\��b�/�F�T\�V��#�
|
1
|
+
Z9}O��Tg+��zvQ�7�w����jh%/4�A�Ѱc�)�0A��)��u~�.]�!S�
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module WaterDrop
|
4
|
-
module Patches
|
5
|
-
module Rdkafka
|
6
|
-
# Patches for the producer client
|
7
|
-
module Client
|
8
|
-
# @param _object_id [nil] rdkafka API compatibility argument
|
9
|
-
# @param timeout_ms [Integer] final flush timeout in ms
|
10
|
-
def close(_object_id = nil, timeout_ms = 5_000)
|
11
|
-
return unless @native
|
12
|
-
|
13
|
-
# Indicate to polling thread that we're closing
|
14
|
-
@polling_thread[:closing] = true
|
15
|
-
# Wait for the polling thread to finish up
|
16
|
-
@polling_thread.join
|
17
|
-
|
18
|
-
::Rdkafka::Bindings.rd_kafka_flush(@native, timeout_ms)
|
19
|
-
::Rdkafka::Bindings.rd_kafka_destroy(@native)
|
20
|
-
|
21
|
-
@native = nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
::Rdkafka::Bindings.attach_function(
|
29
|
-
:rd_kafka_flush,
|
30
|
-
%i[pointer int],
|
31
|
-
:void
|
32
|
-
)
|
33
|
-
|
34
|
-
Rdkafka::Producer::Client.prepend WaterDrop::Patches::Rdkafka::Client
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module WaterDrop
|
4
|
-
# Patches to external components
|
5
|
-
module Patches
|
6
|
-
# Rdkafka related patches
|
7
|
-
module Rdkafka
|
8
|
-
# Rdkafka::Metadata patches
|
9
|
-
module Metadata
|
10
|
-
# Errors upon which we retry the metadata fetch
|
11
|
-
RETRIED_ERRORS = %i[
|
12
|
-
timed_out
|
13
|
-
leader_not_available
|
14
|
-
].freeze
|
15
|
-
|
16
|
-
private_constant :RETRIED_ERRORS
|
17
|
-
|
18
|
-
# We overwrite this method because there were reports of metadata operation timing out
|
19
|
-
# when Kafka was under stress. While the messages dispatch will be retried, metadata
|
20
|
-
# fetch happens prior to that, effectively crashing the process. Metadata fetch was not
|
21
|
-
# being retried at all.
|
22
|
-
#
|
23
|
-
# @param args [Array<Object>] all the metadata original arguments
|
24
|
-
def initialize(*args)
|
25
|
-
attempt ||= 0
|
26
|
-
attempt += 1
|
27
|
-
|
28
|
-
super(*args)
|
29
|
-
rescue ::Rdkafka::RdkafkaError => e
|
30
|
-
raise unless RETRIED_ERRORS.include?(e.code)
|
31
|
-
raise if attempt > 10
|
32
|
-
|
33
|
-
backoff_factor = 2**attempt
|
34
|
-
timeout = backoff_factor * 0.1
|
35
|
-
|
36
|
-
sleep(timeout)
|
37
|
-
|
38
|
-
retry
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
::Rdkafka::Metadata.prepend ::WaterDrop::Patches::Rdkafka::Metadata
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module WaterDrop
|
4
|
-
# Patches to external components
|
5
|
-
module Patches
|
6
|
-
# Rdkafka related patches
|
7
|
-
module Rdkafka
|
8
|
-
# Rdkafka::Producer patches
|
9
|
-
module Producer
|
10
|
-
include ::Karafka::Core::Helpers::Time
|
11
|
-
|
12
|
-
# Cache partitions count for 30 seconds
|
13
|
-
PARTITIONS_COUNT_TTL = 30_000
|
14
|
-
|
15
|
-
private_constant :PARTITIONS_COUNT_TTL
|
16
|
-
|
17
|
-
# @param args [Object] arguments accepted by the original rdkafka producer
|
18
|
-
def initialize(*args)
|
19
|
-
super
|
20
|
-
|
21
|
-
@_partitions_count_cache = Concurrent::Hash.new do |cache, topic|
|
22
|
-
topic_metadata = ::Rdkafka::Metadata.new(inner_kafka, topic).topics&.first
|
23
|
-
|
24
|
-
cache[topic] = [
|
25
|
-
monotonic_now,
|
26
|
-
topic_metadata ? topic_metadata[:partition_count] : nil
|
27
|
-
]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Adds a method that allows us to get the native kafka producer name
|
32
|
-
#
|
33
|
-
# In between rdkafka versions, there are internal changes that force us to add some extra
|
34
|
-
# magic to support all the versions.
|
35
|
-
#
|
36
|
-
# @return [String] producer instance name
|
37
|
-
def name
|
38
|
-
@_name ||= ::Rdkafka::Bindings.rd_kafka_name(inner_kafka)
|
39
|
-
end
|
40
|
-
|
41
|
-
# This patch makes sure we cache the partition count for a given topic for given time
|
42
|
-
# This prevents us in case someone uses `partition_key` from querying for the count with
|
43
|
-
# each message. Instead we query once every 30 seconds at most
|
44
|
-
#
|
45
|
-
# @param topic [String] topic name
|
46
|
-
# @return [Integer] partition count for a given topic
|
47
|
-
def partition_count(topic)
|
48
|
-
closed_producer_check(__method__)
|
49
|
-
|
50
|
-
@_partitions_count_cache.delete_if do |_, cached|
|
51
|
-
monotonic_now - cached.first > PARTITIONS_COUNT_TTL
|
52
|
-
end
|
53
|
-
|
54
|
-
@_partitions_count_cache[topic].last
|
55
|
-
end
|
56
|
-
|
57
|
-
# @return [FFI::Pointer] pointer to the raw librdkafka
|
58
|
-
def inner_kafka
|
59
|
-
unless @_inner_kafka
|
60
|
-
version = ::Gem::Version.new(::Rdkafka::VERSION)
|
61
|
-
|
62
|
-
if version < ::Gem::Version.new('0.12.0')
|
63
|
-
@_inner_kafka = @native_kafka
|
64
|
-
elsif version < ::Gem::Version.new('0.13.0.beta.1')
|
65
|
-
@_inner_kafka = @client.native
|
66
|
-
else
|
67
|
-
@_inner_kafka = @native_kafka.inner
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
@_inner_kafka
|
72
|
-
end
|
73
|
-
|
74
|
-
# Closes our librdkafka instance with the flush patch
|
75
|
-
# @param timeout_ms [Integer] flush timeout
|
76
|
-
def close(timeout_ms = 5_000)
|
77
|
-
ObjectSpace.undefine_finalizer(self)
|
78
|
-
|
79
|
-
@client.close(nil, timeout_ms)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
::Rdkafka::Producer.prepend ::WaterDrop::Patches::Rdkafka::Producer
|