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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed73a2332f0161e71e385fd2250c96bc43383eead9f2945b2580226f855f2643
4
- data.tar.gz: 20705696d8534e5b3e10e84a4ae85f05a01025007879b0f59cff7d26f61d28e3
3
+ metadata.gz: 5e637029ce9d9113e2d64cadcec57ac980602d489f2207507194082065604b16
4
+ data.tar.gz: 21d0a5a643b3e48603fe8e8adb13dbe827a0b9b50871675e57aa62b71abe7573
5
5
  SHA512:
6
- metadata.gz: 92533a6e46992a10b2c7d4f3c6cece7f905697cb3c7c2576ec3f0364400b14c71695f1202d8c4b896168753c1d38b888e996632e6894a7cdbdc9f92e940540a6
7
- data.tar.gz: '0945428add01cbf32e84c15458db0e39cbc1caabf8e7af9db4221b8e6149162a26946206632858154c202e702c2564a0857d9d420cce3711916f64ccfa1eab87'
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 invite loop.
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.0)
5
- karafka-core (>= 2.0.13, < 3.0.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.4.3)
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.12.0)
23
+ i18n (1.14.1)
24
24
  concurrent-ruby (~> 1.0)
25
- karafka-core (2.0.13)
25
+ karafka-core (2.1.0.beta1)
26
26
  concurrent-ruby (>= 1.1)
27
- karafka-rdkafka (>= 0.12.3)
28
- karafka-rdkafka (0.12.3)
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.1)
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.1)
39
+ rspec-core (3.12.2)
40
40
  rspec-support (~> 3.12.0)
41
- rspec-expectations (3.12.2)
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.7)
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.
@@ -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(@config.max_wait_timeout) if @client
146
+ client.close if @client
142
147
 
143
148
  # Remove callbacks runners that were registered
144
149
  ::Karafka::Core::Instrumentation.statistics_callbacks.delete(@id)
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '2.6.0'
6
+ VERSION = '2.6.1.beta1'
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.0.13', '< 3.0.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.0
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-11 00:00:00.000000000 Z
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.13
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.13
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: '0'
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
- ��Mܩ;s�}դ���.]'�z�5U�jO+N4�A�YNV��̦�Y�o�u@��A�ם��������i=h��W0�w�T���lU����C���r�<Y�����]2�w8:���FS atcPw!�MK�:�o��>ɯ}z��̯籌�G�ġ�5)�]%^��Kw�<�j��f(��l����uozn�`H� qY�#? �&�6�@�r+oK�������A{�ǖ_N���3ar���Y�����x��л�
2
- ٹ��@��l�.K��Z�2��'�#�1V)�J8�B;�˲�XsIx���~�{�])����$�-v���_�gԖd}���MM>�5lF\��b�/�F�T\�V��#�
1
+ Z9}O��Tg+��zvQ7�w����jh%/4A�Ѱ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