waterdrop 2.4.1 → 2.4.3

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: 70b84fa09ce807d6d72679917d6c9b98a4dd15b9eb50f0ae9c556acc6f084632
4
- data.tar.gz: 8ccffe9e5331865dc93ab4c8b4b8ace2e0c3297f164c378b7919a14e307edf70
3
+ metadata.gz: 065c53c0e711cfe49e718a321ce64740b68a45bd6ac477c9eaf2a79876de8df7
4
+ data.tar.gz: e77179ca5162c4862369838197a62063b5127b4d3a72b7ab08f85f930cee6ea6
5
5
  SHA512:
6
- metadata.gz: 66f25845bada1a7de0f6bd100b7966f246604701f0394891bc959817f222b739a73fc674b49d288ebf3674c85e9872db37069771f347fad98eeade561373610c
7
- data.tar.gz: 308eafaec616bf936517086de4bcee0efa03ed555ad91a061588b781d9214198fa67258a0d7044eae523fbba4da57fa447ddafdcf3169a234cdc4b0785151c6e
6
+ metadata.gz: 76af1a5f87a5f31bda8b9f5f111173e1992f6d5ddc85fa2b43d5e1fbd45b93e67601691cbf13b3b2a2e8eb49bc04196b84c5eb81c5b0bd6e11bbe014220fe821
7
+ data.tar.gz: 27c667d0c93f6948a85d9411fd1dfa46bd38ebb36f7c6907785658bb58ae3001b8d2b81bcb1a9faac64acc5248bc1300a3530736cdd7193b155e01eca4eefbbe
checksums.yaml.gz.sig CHANGED
@@ -1,3 +1,2 @@
1
- �k1�|��~=����WE��K�f���k�ېJ��rT,�����ß�UcZPxg
2
- �AE���-W��4NzK���5�͍x]�2�:��1�y
3
- �8� ��L��Q4WI��F�d�t�İw�Z��k#�E�24��E�*-�e�w�A-�u ���ä��Q�;j���h#���<��F!�oJFb;�0r��Θw�x��������Z�c�u��y���`�5�h_��w�t��k;�~yy���2_i�P��F_ �����V�,Ƥ�x��l�N�
1
+ ߸'��A�=�Y撂.�~h��H�ύ̋�`��FI��Bw�+&�����)*�7����ʣ5w ��3T���)�K����s���9lPӐ*5 �W�>��'J�����}^2YcN׬b��~[�� 9�?�j5o�պ�{���2��a8�
2
+ ��,��S
@@ -0,0 +1 @@
1
+ custom: ['https://karafka.io/#become-pro']
@@ -23,13 +23,15 @@ jobs:
23
23
  - ruby: '3.1'
24
24
  coverage: 'true'
25
25
  steps:
26
- - uses: actions/checkout@v2
26
+ - uses: actions/checkout@v3
27
27
  - name: Install package dependencies
28
28
  run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
29
29
  - name: Set up Ruby
30
30
  uses: ruby/setup-ruby@v1
31
31
  with:
32
32
  ruby-version: ${{matrix.ruby}}
33
+ - name: Remove libzstd-dev to check no supported compressions
34
+ run: sudo apt-get -y remove libzstd-dev
33
35
  - name: Run Kafka with docker-compose
34
36
  # We need to give Kafka enough time to start and create all the needed topics, etc
35
37
  # If anyone has a better idea on how to do it smart and easily, please contact me
@@ -54,7 +56,7 @@ jobs:
54
56
  strategy:
55
57
  fail-fast: false
56
58
  steps:
57
- - uses: actions/checkout@v2
59
+ - uses: actions/checkout@v3
58
60
  with:
59
61
  fetch-depth: 0
60
62
  - name: Set up Ruby
@@ -73,7 +75,7 @@ jobs:
73
75
  strategy:
74
76
  fail-fast: false
75
77
  steps:
76
- - uses: actions/checkout@v2
78
+ - uses: actions/checkout@v3
77
79
  with:
78
80
  fetch-depth: 0
79
81
  - name: Run Coditsu
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.1.2
1
+ 3.1.3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # WaterDrop changelog
2
2
 
3
+ ## 2.4.3 (2022-12-07)
4
+ - Support for librdkafka 0.13
5
+ - Update Github Actions
6
+ - Change auto-generated id from `SecureRandom#uuid` to `SecureRandom#hex(6)`
7
+ - Remove shared components that were moved to `karafka-core` from WaterDrop
8
+
9
+ ## 2.4.2 (2022-09-29)
10
+ - Allow sending tombstone messages (#267)
11
+
3
12
  ## 2.4.1 (2022-08-01)
4
13
  - Replace local statistics decorator with the one extracted to `karafka-core`.
5
14
 
data/Gemfile.lock CHANGED
@@ -1,15 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- waterdrop (2.4.1)
5
- karafka-core (>= 2.0.2, < 3.0.0)
6
- rdkafka (>= 0.10)
4
+ waterdrop (2.4.3)
5
+ karafka-core (>= 2.0.6, < 3.0.0)
7
6
  zeitwerk (~> 2.3)
8
7
 
9
8
  GEM
10
9
  remote: https://rubygems.org/
11
10
  specs:
12
- activesupport (7.0.3.1)
11
+ activesupport (7.0.4)
13
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
13
  i18n (>= 1.6, < 2)
15
14
  minitest (>= 5.1)
@@ -23,28 +22,29 @@ GEM
23
22
  ffi (1.15.5)
24
23
  i18n (1.12.0)
25
24
  concurrent-ruby (~> 1.0)
26
- karafka-core (2.0.2)
25
+ karafka-core (2.0.6)
27
26
  concurrent-ruby (>= 1.1)
27
+ rdkafka (>= 0.12)
28
28
  mini_portile2 (2.8.0)
29
- minitest (5.16.2)
29
+ minitest (5.16.3)
30
30
  rake (13.0.6)
31
31
  rdkafka (0.12.0)
32
32
  ffi (~> 1.15)
33
33
  mini_portile2 (~> 2.6)
34
34
  rake (> 12)
35
- rspec (3.11.0)
36
- rspec-core (~> 3.11.0)
37
- rspec-expectations (~> 3.11.0)
38
- rspec-mocks (~> 3.11.0)
39
- rspec-core (3.11.0)
40
- rspec-support (~> 3.11.0)
41
- rspec-expectations (3.11.0)
35
+ rspec (3.12.0)
36
+ rspec-core (~> 3.12.0)
37
+ rspec-expectations (~> 3.12.0)
38
+ rspec-mocks (~> 3.12.0)
39
+ rspec-core (3.12.0)
40
+ rspec-support (~> 3.12.0)
41
+ rspec-expectations (3.12.0)
42
42
  diff-lcs (>= 1.2.0, < 2.0)
43
- rspec-support (~> 3.11.0)
44
- rspec-mocks (3.11.1)
43
+ rspec-support (~> 3.12.0)
44
+ rspec-mocks (3.12.0)
45
45
  diff-lcs (>= 1.2.0, < 2.0)
46
- rspec-support (~> 3.11.0)
47
- rspec-support (3.11.0)
46
+ rspec-support (~> 3.12.0)
47
+ rspec-support (3.12.0)
48
48
  simplecov (0.21.2)
49
49
  docile (~> 1.1)
50
50
  simplecov-html (~> 0.11)
@@ -53,9 +53,10 @@ GEM
53
53
  simplecov_json_formatter (0.1.4)
54
54
  tzinfo (2.0.5)
55
55
  concurrent-ruby (~> 1.0)
56
- zeitwerk (2.6.0)
56
+ zeitwerk (2.6.6)
57
57
 
58
58
  PLATFORMS
59
+ arm64-darwin
59
60
  x86_64-linux
60
61
 
61
62
  DEPENDENCIES
@@ -66,4 +67,4 @@ DEPENDENCIES
66
67
  waterdrop!
67
68
 
68
69
  BUNDLED WITH
69
- 2.3.15
70
+ 2.3.26
data/README.md CHANGED
@@ -1,11 +1,5 @@
1
1
  # WaterDrop
2
2
 
3
- **Note**: Documentation presented here refers to WaterDrop `2.x`.
4
-
5
- WaterDrop `2.x` works with Karafka `2.*` and aims to either work as a standalone producer or as a part of the Karafka `2.*`.
6
-
7
- Please refer to [this](https://github.com/karafka/waterdrop/tree/1.4) branch and its documentation for details about WaterDrop `1.*` usage.
8
-
9
3
  [![Build Status](https://github.com/karafka/waterdrop/workflows/ci/badge.svg)](https://github.com/karafka/waterdrop/actions?query=workflow%3Aci)
10
4
  [![Gem Version](https://badge.fury.io/rb/waterdrop.svg)](http://badge.fury.io/rb/waterdrop)
11
5
  [![Join the chat at https://slack.karafka.io](https://raw.githubusercontent.com/karafka/misc/master/slack.svg)](https://slack.karafka.io)
@@ -35,6 +29,7 @@ It:
35
29
  * [Buffering](#buffering)
36
30
  + [Using WaterDrop to buffer messages based on the application logic](#using-waterdrop-to-buffer-messages-based-on-the-application-logic)
37
31
  + [Using WaterDrop with rdkafka buffers to achieve periodic auto-flushing](#using-waterdrop-with-rdkafka-buffers-to-achieve-periodic-auto-flushing)
32
+ * [Compression](#compression)
38
33
  - [Instrumentation](#instrumentation)
39
34
  * [Usage statistics](#usage-statistics)
40
35
  * [Error notifications](#error-notifications)
@@ -161,9 +156,14 @@ Keep in mind, that message you want to send should be either binary or stringifi
161
156
 
162
157
  ### Using WaterDrop across the application and with Ruby on Rails
163
158
 
164
- If you plan to both produce and consume messages using Kafka, you should install and use [Karafka](https://github.com/karafka/karafka). It integrates automatically with Ruby on Rails applications and auto-configures WaterDrop producer to make it accessible via `Karafka#producer` method.
159
+ If you plan to both produce and consume messages using Kafka, you should install and use [Karafka](https://github.com/karafka/karafka). It integrates automatically with Ruby on Rails applications and auto-configures WaterDrop producer to make it accessible via `Karafka#producer` method:
160
+
161
+ ```ruby
162
+ event = Events.last
163
+ Karafka.producer.produce_async(topic: 'events', payload: event.to_json)
164
+ ```
165
165
 
166
- If you want to only produce messages from within your application, since WaterDrop is thread-safe you can create a single instance in an initializer like so:
166
+ If you want to only produce messages from within your application without consuming with Karafka, since WaterDrop is thread-safe you can create a single instance in an initializer like so:
167
167
 
168
168
  ```ruby
169
169
  KAFKA_PRODUCER = WaterDrop::Producer.new
@@ -200,6 +200,35 @@ WaterDrop producers support buffering messages in their internal buffers and on
200
200
 
201
201
  This means that depending on your use case, you can achieve both granular buffering and flushing control when needed with context awareness and periodic and size-based flushing functionalities.
202
202
 
203
+ ### Compression
204
+
205
+ WaterDrop supports following compression types:
206
+
207
+ - `gzip`
208
+ - `zstd`
209
+ - `lz4`
210
+ - `snappy`
211
+
212
+ To use compression, set `kafka` scope `compression.codec` setting. You can also optionally indicate the `compression.level`:
213
+
214
+ ```ruby
215
+ producer = WaterDrop::Producer.new
216
+
217
+ producer.setup do |config|
218
+ config.kafka = {
219
+ 'bootstrap.servers': 'localhost:9092',
220
+ 'compression.codec': 'gzip',
221
+ 'compression.level': 6
222
+ }
223
+ end
224
+ ```
225
+
226
+ **Note**: In order to use `zstd`, you need to install `libzstd-dev`:
227
+
228
+ ```bash
229
+ apt-get install -y libzstd-dev
230
+ ```
231
+
203
232
  #### Using WaterDrop to buffer messages based on the application logic
204
233
 
205
234
  ```ruby
@@ -0,0 +1,26 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQDDAdjb250
3
+ YWN0MRcwFQYKCZImiZPyLGQBGRYHa2FyYWZrYTESMBAGCgmSJomT8ixkARkWAmlv
4
+ MB4XDTIyMDgxOTE3MjEzN1oXDTIzMDgxOTE3MjEzN1owPzEQMA4GA1UEAwwHY29u
5
+ dGFjdDEXMBUGCgmSJomT8ixkARkWB2thcmFma2ExEjAQBgoJkiaJk/IsZAEZFgJp
6
+ bzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAODzeO3L6lxdATzMHKNW
7
+ jFA/GGunoPuylO/BMzy8RiQHh7VIvysAKs0tHhTx3g2D0STDpF+hcQcPELFikiT2
8
+ F+1wOHj/SsrK7VKqfA8+gq04hKc5sQoX2Egf9k3V0YJ3eZ6R/koHkQ8A0TVt0w6F
9
+ ZQckoV4MqnEAx0g/FZN3mnHTlJ3VFLSBqJEIe+S6FZMl92mSv+hTrlUG8VaYxSfN
10
+ lTCvnKk284F6QZq5XIENLRmcDd/3aPBLnLwNnyMyhB+6gK8cUO+CFlDO5tjo/aBA
11
+ rUnl++wGG0JooF1ed0v+evOn9KoMBG6rHewcf79qJbVOscbD8qSAmo+sCXtcFryr
12
+ KRMTB8gNbowJkFRJDEe8tfRy11u1fYzFg/qNO82FJd62rKAw2wN0C29yCeQOPRb1
13
+ Cw9Y4ZwK9VFNEcV9L+3pHTHn2XfuZHtDaG198VweiF6raFO4yiEYccodH/USP0L5
14
+ cbcCFtmu/4HDSxL1ByQXO84A0ybJuk3/+aPUSXe9C9U8fwIDAQABo3cwdTAJBgNV
15
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUSlcEakb7gfn/5E2WY6z73BF/
16
+ iZkwHQYDVR0RBBYwFIESY29udGFjdEBrYXJhZmthLmlvMB0GA1UdEgQWMBSBEmNv
17
+ bnRhY3RAa2FyYWZrYS5pbzANBgkqhkiG9w0BAQsFAAOCAYEA1aS+E7RXJ1w9g9mJ
18
+ G0NzFxe64OEuENosNlvYQCbRKGCXAU1qqelYkBQHseRgRKxLICrnypRo9IEobyHa
19
+ vDnJ4r7Tsb34dleqQW2zY/obG+cia3Ym2JsegXWF7dDOzCXJ4FN8MFoT2jHlqLLw
20
+ yrap0YO5zx0GSQ0Dwy8h2n2v2vanMEeCx7iNm3ERgR5WuN5sjzWoz2A/JLEEcK0C
21
+ EnAGKCWAd1fuG8IemDjT1edsd5FyYR4bIX0m+99oDuFZyPiiIbalmyYiSBBp59Yb
22
+ Q0P8zeBi4OfwCZNcxqz0KONmw9JLNv6DgyEAH5xe/4JzhMEgvIRiPj0pHfA7oqQF
23
+ KUNqvD1KlxbEC+bZfE5IZhnqYLdld/Ksqd22FI1RBhiS1Ejfsj99LVIm9cBuZEY2
24
+ Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
25
+ MGU0FeSV2Yj7Xc2x/7BzLK8xQn5l7Yy75iPF+KP3vVmDHnNl
26
+ -----END CERTIFICATE-----
data/config/errors.yml CHANGED
@@ -17,7 +17,7 @@ en:
17
17
  topic_format: 'does not match the topic allowed format'
18
18
  partition_key_format: must be a non-empty string
19
19
  timestamp_format: must be either time or integer
20
- payload_format: must be string
20
+ payload_format: must be string or nil
21
21
  headers_format: must be a hash
22
22
  key_format: must be a non-empty string
23
23
  payload_max_size: is more than `max_payload_size` config value
@@ -22,7 +22,7 @@ module WaterDrop
22
22
  setting(
23
23
  :id,
24
24
  default: false,
25
- constructor: ->(id) { id || SecureRandom.uuid }
25
+ constructor: ->(id) { id || SecureRandom.hex(6) }
26
26
  )
27
27
  # option [Instance] logger that we want to use
28
28
  # @note Due to how rdkafka works, this setting is global for all the producers
@@ -77,7 +77,7 @@ module WaterDrop
77
77
  # Propagates the kafka setting defaults unless they are already present
78
78
  # This makes it easier to set some values that users usually don't change but still allows them
79
79
  # to overwrite the whole hash if they want to
80
- # @param config [WaterDrop::Configurable::Node] config of this producer
80
+ # @param config [Karafka::Core::Configurable::Node] config of this producer
81
81
  def merge_kafka_defaults!(config)
82
82
  KAFKA_DEFAULTS.each do |key, value|
83
83
  next if config.kafka.key?(key)
@@ -3,7 +3,7 @@
3
3
  module WaterDrop
4
4
  module Contracts
5
5
  # Contract with validation rules for validating that all the message options that
6
- # we provide to producer ale valid and usable
6
+ # we provide to producer are valid and usable
7
7
  class Message < ::Karafka::Core::Contractable::Contract
8
8
  configure do |config|
9
9
  config.error_messages = YAML.safe_load(
@@ -27,21 +27,21 @@ module WaterDrop
27
27
  end
28
28
 
29
29
  required(:topic) { |val| val.is_a?(String) && TOPIC_REGEXP.match?(val) }
30
- required(:payload) { |val| val.is_a?(String) }
30
+ required(:payload) { |val| val.nil? || val.is_a?(String) }
31
31
  optional(:key) { |val| val.nil? || (val.is_a?(String) && !val.empty?) }
32
32
  optional(:partition) { |val| val.is_a?(Integer) && val >= -1 }
33
33
  optional(:partition_key) { |val| val.nil? || (val.is_a?(String) && !val.empty?) }
34
34
  optional(:timestamp) { |val| val.nil? || (val.is_a?(Time) || val.is_a?(Integer)) }
35
35
  optional(:headers) { |val| val.nil? || val.is_a?(Hash) }
36
36
 
37
- virtual do |config, errors|
37
+ virtual do |message, errors|
38
38
  next true unless errors.empty?
39
- next true unless config.key?(:headers)
40
- next true if config[:headers].nil?
39
+ next true unless message.key?(:headers)
40
+ next true if message[:headers].nil?
41
41
 
42
42
  errors = []
43
43
 
44
- config.fetch(:headers).each do |key, value|
44
+ message.fetch(:headers).each do |key, value|
45
45
  errors << [%i[headers], :invalid_key_type] unless key.is_a?(String)
46
46
  errors << [%i[headers], :invalid_value_type] unless value.is_a?(String)
47
47
  end
@@ -49,9 +49,10 @@ module WaterDrop
49
49
  errors
50
50
  end
51
51
 
52
- virtual do |config, errors, validator|
52
+ virtual do |message, errors, validator|
53
53
  next true unless errors.empty?
54
- next true if config[:payload].bytesize <= validator.max_payload_size
54
+ next if message[:payload].nil? # tombstone payload
55
+ next true if message[:payload].bytesize <= validator.max_payload_size
55
56
 
56
57
  [[%i[payload], :max_size]]
57
58
  end
@@ -66,7 +66,7 @@ module WaterDrop
66
66
 
67
67
  # Hooks up to WaterDrop instrumentation for emitted statistics
68
68
  #
69
- # @param event [WaterDrop::Monitor::Event]
69
+ # @param event [Karafka::Core::Monitoring::Event]
70
70
  def on_statistics_emitted(event)
71
71
  statistics = event[:statistics]
72
72
 
@@ -77,13 +77,13 @@ module WaterDrop
77
77
 
78
78
  # Increases the errors count by 1
79
79
  #
80
- # @param _event [WaterDrop::Monitor::Event]
80
+ # @param _event [Karafka::Core::Monitoring::Event]
81
81
  def on_error_occurred(_event)
82
82
  count('error_occurred', 1, tags: default_tags)
83
83
  end
84
84
 
85
85
  # Increases acknowledged messages counter
86
- # @param _event [WaterDrop::Monitor::Event]
86
+ # @param _event [Karafka::Core::Monitoring::Event]
87
87
  def on_message_acknowledged(_event)
88
88
  increment('acknowledged', tags: default_tags)
89
89
  end
@@ -93,12 +93,12 @@ module WaterDrop
93
93
  produced_async
94
94
  ].each do |event_scope|
95
95
  class_eval <<~METHODS, __FILE__, __LINE__ + 1
96
- # @param event [WaterDrop::Monitor::Event]
96
+ # @param event [Karafka::Core::Monitoring::Event]
97
97
  def on_message_#{event_scope}(event)
98
98
  report_message(event[:message][:topic], :#{event_scope})
99
99
  end
100
100
 
101
- # @param event [WaterDrop::Monitor::Event]
101
+ # @param event [Karafka::Core::Monitoring::Event]
102
102
  def on_messages_#{event_scope}(event)
103
103
  event[:messages].each do |message|
104
104
  report_message(message[:topic], :#{event_scope})
@@ -113,7 +113,7 @@ module WaterDrop
113
113
  messages_buffered
114
114
  ].each do |event_scope|
115
115
  class_eval <<~METHODS, __FILE__, __LINE__ + 1
116
- # @param event [WaterDrop::Monitor::Event]
116
+ # @param event [Karafka::Core::Monitoring::Event]
117
117
  def on_#{event_scope}(event)
118
118
  histogram(
119
119
  'buffer.size',
@@ -131,7 +131,7 @@ module WaterDrop
131
131
  flushed_async
132
132
  ].each do |event_scope|
133
133
  class_eval <<~METHODS, __FILE__, __LINE__ + 1
134
- # @param event [WaterDrop::Monitor::Event]
134
+ # @param event [Karafka::Core::Monitoring::Event]
135
135
  def on_buffer_#{event_scope}(event)
136
136
  event[:messages].each do |message|
137
137
  report_message(message[:topic], :#{event_scope})
@@ -8,14 +8,22 @@ module WaterDrop
8
8
  # Rdkafka::Producer patches
9
9
  module Producer
10
10
  # Adds a method that allows us to get the native kafka producer name
11
+ #
12
+ # In between rdkafka versions, there are internal changes that force us to add some extra
13
+ # magic to support all the versions.
14
+ #
11
15
  # @return [String] producer instance name
12
16
  def name
13
17
  unless @_native
14
18
  version = ::Gem::Version.new(::Rdkafka::VERSION)
15
- change = ::Gem::Version.new('0.12.0')
16
- # 0.12.0 changed how the native producer client reference works.
17
- # This code supports both older and newer versions of rdkafka
18
- @_native = version >= change ? @client.native : @native_kafka
19
+
20
+ if version < ::Gem::Version.new('0.12.0')
21
+ @native = @native_kafka
22
+ elsif version < ::Gem::Version.new('0.13.0.beta.1')
23
+ @_native = @client.native
24
+ else
25
+ @_native = @native_kafka.inner
26
+ end
19
27
  end
20
28
 
21
29
  ::Rdkafka::Bindings.rd_kafka_name(@_native)
@@ -82,13 +82,13 @@ module WaterDrop
82
82
  @client = Builder.new.call(self, @config)
83
83
 
84
84
  # Register statistics runner for this particular type of callbacks
85
- ::WaterDrop::Instrumentation.statistics_callbacks.add(
85
+ ::Karafka::Core::Instrumentation.statistics_callbacks.add(
86
86
  @id,
87
87
  Instrumentation::Callbacks::Statistics.new(@id, @client.name, @config.monitor)
88
88
  )
89
89
 
90
90
  # Register error tracking callback
91
- ::WaterDrop::Instrumentation.error_callbacks.add(
91
+ ::Karafka::Core::Instrumentation.error_callbacks.add(
92
92
  @id,
93
93
  Instrumentation::Callbacks::Error.new(@id, @client.name, @config.monitor)
94
94
  )
@@ -125,8 +125,8 @@ module WaterDrop
125
125
  client.close if @client
126
126
 
127
127
  # Remove callbacks runners that were registered
128
- ::WaterDrop::Instrumentation.statistics_callbacks.delete(@id)
129
- ::WaterDrop::Instrumentation.error_callbacks.delete(@id)
128
+ ::Karafka::Core::Instrumentation.statistics_callbacks.delete(@id)
129
+ ::Karafka::Core::Instrumentation.error_callbacks.delete(@id)
130
130
 
131
131
  @status.closed!
132
132
  end
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '2.4.1'
6
+ VERSION = '2.4.3'
7
7
  end
data/lib/waterdrop.rb CHANGED
@@ -3,12 +3,11 @@
3
3
  # External components
4
4
  # delegate should be removed because we don't need it, we just add it because of ruby-kafka
5
5
  %w[
6
- karafka-core
7
6
  forwardable
8
- rdkafka
9
7
  json
10
8
  zeitwerk
11
9
  securerandom
10
+ karafka-core
12
11
  ].each { |lib| require lib }
13
12
 
14
13
  # WaterDrop library
@@ -27,9 +26,3 @@ loader.inflector.inflect('waterdrop' => 'WaterDrop')
27
26
  loader.ignore("#{__dir__}/waterdrop/instrumentation/vendors/**/*.rb")
28
27
  loader.setup
29
28
  loader.eager_load
30
-
31
- # Rdkafka uses a single global callback for things. We bypass that by injecting a manager for
32
- # each callback type. Callback manager allows us to register more than one callback
33
- # @note Those managers are also used by Karafka for consumer related statistics
34
- Rdkafka::Config.statistics_callback = WaterDrop::Instrumentation.statistics_callbacks
35
- Rdkafka::Config.error_callback = WaterDrop::Instrumentation.error_callbacks
data/waterdrop.gemspec CHANGED
@@ -10,14 +10,13 @@ Gem::Specification.new do |spec|
10
10
  spec.version = ::WaterDrop::VERSION
11
11
  spec.platform = Gem::Platform::RUBY
12
12
  spec.authors = ['Maciej Mensfeld']
13
- spec.email = %w[maciej@mensfeld.pl]
13
+ spec.email = %w[contact@karafka.io]
14
14
  spec.homepage = 'https://karafka.io'
15
15
  spec.summary = 'Kafka messaging made easy!'
16
16
  spec.description = spec.summary
17
17
  spec.license = 'MIT'
18
18
 
19
- spec.add_dependency 'karafka-core', '>= 2.0.2', '< 3.0.0'
20
- spec.add_dependency 'rdkafka', '>= 0.10'
19
+ spec.add_dependency 'karafka-core', '>= 2.0.6', '< 3.0.0'
21
20
  spec.add_dependency 'zeitwerk', '~> 2.3'
22
21
 
23
22
  spec.required_ruby_version = '>= 2.7'
@@ -26,7 +25,7 @@ Gem::Specification.new do |spec|
26
25
  spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
27
26
  end
28
27
 
29
- spec.cert_chain = %w[certs/mensfeld.pem]
28
+ spec.cert_chain = %w[certs/cert_chain.pem]
30
29
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
31
30
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
32
31
  spec.require_paths = %w[lib]
data.tar.gz.sig CHANGED
@@ -1,3 +1 @@
1
- ����j��o��@:&" �k |n�|�gY�����ƨ�}�� ��=�*ʍD ��ι��Ru��f��\ CAk���,�,�]p�J�Ul��BqhON�T �+�h����� ���9,*�u���5
2
- ���9!������Ľ�ㄘ�|�
3
- p�u�}���������R�|���M���7���)���9d�
4
- V��˳��
1
+ V�i�ڈg� �J�Ł�J})g�������.�J�QSn̡��؊��@lG_t&A���<e{���|���=@;��@��p�x[( M��8��_+|���0[��$���g���t #XIw?�=X�%Ԉ�qoA�:��}��a�T���`� ��K�
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.4.1
4
+ version: 2.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -10,31 +10,32 @@ bindir: bin
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
- MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhtYWNp
14
- ZWovREM9bWVuc2ZlbGQvREM9cGwwHhcNMjEwODExMTQxNTEzWhcNMjIwODExMTQx
15
- NTEzWjAjMSEwHwYDVQQDDBhtYWNpZWovREM9bWVuc2ZlbGQvREM9cGwwggGiMA0G
16
- CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDV2jKH4Ti87GM6nyT6D+ESzTI0MZDj
17
- ak2/TEwnxvijMJyCCPKT/qIkbW4/f0VHM4rhPr1nW73sb5SZBVFCLlJcOSKOBdUY
18
- TMY+SIXN2EtUaZuhAOe8LxtxjHTgRHvHcqUQMBENXTISNzCo32LnUxweu66ia4Pd
19
- 1mNRhzOqNv9YiBZvtBf7IMQ+sYdOCjboq2dlsWmJiwiDpY9lQBTnWORnT3mQxU5x
20
- vPSwnLB854cHdCS8fQo4DjeJBRZHhEbcE5sqhEMB3RZA3EtFVEXOxlNxVTS3tncI
21
- qyNXiWDaxcipaens4ObSY1C2HTV7OWb7OMqSCIybeYTSfkaSdqmcl4S6zxXkjH1J
22
- tnjayAVzD+QVXGijsPLE2PFnJAh9iDET2cMsjabO1f6l1OQNyAtqpcyQcgfnyW0z
23
- g7tGxTYD+6wJHffM9d9txOUw6djkF6bDxyqB8lo4Z3IObCx18AZjI9XPS9QG7w6q
24
- LCWuMG2lkCcRgASqaVk9fEf9yMc2xxz5o3kCAwEAAaN3MHUwCQYDVR0TBAIwADAL
25
- BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFBqUFCKCOe5IuueUVqOB991jyCLLMB0GA1Ud
26
- EQQWMBSBEm1hY2llakBtZW5zZmVsZC5wbDAdBgNVHRIEFjAUgRJtYWNpZWpAbWVu
27
- c2ZlbGQucGwwDQYJKoZIhvcNAQELBQADggGBADD0/UuTTFgW+CGk2U0RDw2RBOca
28
- W2LTF/G7AOzuzD0Tc4voc7WXyrgKwJREv8rgBimLnNlgmFJLmtUCh2U/MgxvcilH
29
- yshYcbseNvjkrtYnLRlWZR4SSB6Zei5AlyGVQLPkvdsBpNegcG6w075YEwzX/38a
30
- 8V9B/Yri2OGELBz8ykl7BsXUgNoUPA/4pHF6YRLz+VirOaUIQ4JfY7xGj6fSOWWz
31
- /rQ/d77r6o1mfJYM/3BRVg73a3b7DmRnE5qjwmSaSQ7u802pJnLesmArch0xGCT/
32
- fMmRli1Qb+6qOTl9mzD6UDMAyFR4t6MStLm0mIEqM0nBO5nUdUWbC7l9qXEf8XBE
33
- 2DP28p3EqSuS+lKbAWKcqv7t0iRhhmaod+Yn9mcrLN1sa3q3KSQ9BCyxezCD4Mk2
34
- R2P11bWoCtr70BsccVrN8jEhzwXngMyI2gVt750Y+dbTu1KgRqZKp/ECe7ZzPzXj
35
- pIy9vHxTANKYVyI4qj8OrFdEM5BQNu8oQpL0iQ==
13
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQDDAdjb250
14
+ YWN0MRcwFQYKCZImiZPyLGQBGRYHa2FyYWZrYTESMBAGCgmSJomT8ixkARkWAmlv
15
+ MB4XDTIyMDgxOTE3MjEzN1oXDTIzMDgxOTE3MjEzN1owPzEQMA4GA1UEAwwHY29u
16
+ dGFjdDEXMBUGCgmSJomT8ixkARkWB2thcmFma2ExEjAQBgoJkiaJk/IsZAEZFgJp
17
+ bzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAODzeO3L6lxdATzMHKNW
18
+ jFA/GGunoPuylO/BMzy8RiQHh7VIvysAKs0tHhTx3g2D0STDpF+hcQcPELFikiT2
19
+ F+1wOHj/SsrK7VKqfA8+gq04hKc5sQoX2Egf9k3V0YJ3eZ6R/koHkQ8A0TVt0w6F
20
+ ZQckoV4MqnEAx0g/FZN3mnHTlJ3VFLSBqJEIe+S6FZMl92mSv+hTrlUG8VaYxSfN
21
+ lTCvnKk284F6QZq5XIENLRmcDd/3aPBLnLwNnyMyhB+6gK8cUO+CFlDO5tjo/aBA
22
+ rUnl++wGG0JooF1ed0v+evOn9KoMBG6rHewcf79qJbVOscbD8qSAmo+sCXtcFryr
23
+ KRMTB8gNbowJkFRJDEe8tfRy11u1fYzFg/qNO82FJd62rKAw2wN0C29yCeQOPRb1
24
+ Cw9Y4ZwK9VFNEcV9L+3pHTHn2XfuZHtDaG198VweiF6raFO4yiEYccodH/USP0L5
25
+ cbcCFtmu/4HDSxL1ByQXO84A0ybJuk3/+aPUSXe9C9U8fwIDAQABo3cwdTAJBgNV
26
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUSlcEakb7gfn/5E2WY6z73BF/
27
+ iZkwHQYDVR0RBBYwFIESY29udGFjdEBrYXJhZmthLmlvMB0GA1UdEgQWMBSBEmNv
28
+ bnRhY3RAa2FyYWZrYS5pbzANBgkqhkiG9w0BAQsFAAOCAYEA1aS+E7RXJ1w9g9mJ
29
+ G0NzFxe64OEuENosNlvYQCbRKGCXAU1qqelYkBQHseRgRKxLICrnypRo9IEobyHa
30
+ vDnJ4r7Tsb34dleqQW2zY/obG+cia3Ym2JsegXWF7dDOzCXJ4FN8MFoT2jHlqLLw
31
+ yrap0YO5zx0GSQ0Dwy8h2n2v2vanMEeCx7iNm3ERgR5WuN5sjzWoz2A/JLEEcK0C
32
+ EnAGKCWAd1fuG8IemDjT1edsd5FyYR4bIX0m+99oDuFZyPiiIbalmyYiSBBp59Yb
33
+ Q0P8zeBi4OfwCZNcxqz0KONmw9JLNv6DgyEAH5xe/4JzhMEgvIRiPj0pHfA7oqQF
34
+ KUNqvD1KlxbEC+bZfE5IZhnqYLdld/Ksqd22FI1RBhiS1Ejfsj99LVIm9cBuZEY2
35
+ Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
36
+ MGU0FeSV2Yj7Xc2x/7BzLK8xQn5l7Yy75iPF+KP3vVmDHnNl
36
37
  -----END CERTIFICATE-----
37
- date: 2022-08-01 00:00:00.000000000 Z
38
+ date: 2022-12-07 00:00:00.000000000 Z
38
39
  dependencies:
39
40
  - !ruby/object:Gem::Dependency
40
41
  name: karafka-core
@@ -42,7 +43,7 @@ dependencies:
42
43
  requirements:
43
44
  - - ">="
44
45
  - !ruby/object:Gem::Version
45
- version: 2.0.2
46
+ version: 2.0.6
46
47
  - - "<"
47
48
  - !ruby/object:Gem::Version
48
49
  version: 3.0.0
@@ -52,24 +53,10 @@ dependencies:
52
53
  requirements:
53
54
  - - ">="
54
55
  - !ruby/object:Gem::Version
55
- version: 2.0.2
56
+ version: 2.0.6
56
57
  - - "<"
57
58
  - !ruby/object:Gem::Version
58
59
  version: 3.0.0
59
- - !ruby/object:Gem::Dependency
60
- name: rdkafka
61
- requirement: !ruby/object:Gem::Requirement
62
- requirements:
63
- - - ">="
64
- - !ruby/object:Gem::Version
65
- version: '0.10'
66
- type: :runtime
67
- prerelease: false
68
- version_requirements: !ruby/object:Gem::Requirement
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: '0.10'
73
60
  - !ruby/object:Gem::Dependency
74
61
  name: zeitwerk
75
62
  requirement: !ruby/object:Gem::Requirement
@@ -86,13 +73,14 @@ dependencies:
86
73
  version: '2.3'
87
74
  description: Kafka messaging made easy!
88
75
  email:
89
- - maciej@mensfeld.pl
76
+ - contact@karafka.io
90
77
  executables: []
91
78
  extensions: []
92
79
  extra_rdoc_files: []
93
80
  files:
94
81
  - ".coditsu/ci.yml"
95
82
  - ".diffend.yml"
83
+ - ".github/FUNDING.yml"
96
84
  - ".github/workflows/ci.yml"
97
85
  - ".gitignore"
98
86
  - ".rspec"
@@ -103,7 +91,7 @@ files:
103
91
  - Gemfile.lock
104
92
  - MIT-LICENSE
105
93
  - README.md
106
- - certs/mensfeld.pem
94
+ - certs/cert_chain.pem
107
95
  - config/errors.yml
108
96
  - docker-compose.yml
109
97
  - lib/waterdrop.rb
@@ -112,17 +100,14 @@ files:
112
100
  - lib/waterdrop/contracts/config.rb
113
101
  - lib/waterdrop/contracts/message.rb
114
102
  - lib/waterdrop/errors.rb
115
- - lib/waterdrop/instrumentation.rb
116
103
  - lib/waterdrop/instrumentation/callbacks/delivery.rb
117
104
  - lib/waterdrop/instrumentation/callbacks/error.rb
118
105
  - lib/waterdrop/instrumentation/callbacks/statistics.rb
119
- - lib/waterdrop/instrumentation/callbacks_manager.rb
120
106
  - lib/waterdrop/instrumentation/logger_listener.rb
121
107
  - lib/waterdrop/instrumentation/monitor.rb
122
108
  - lib/waterdrop/instrumentation/notifications.rb
123
109
  - lib/waterdrop/instrumentation/vendors/datadog/dashboard.json
124
110
  - lib/waterdrop/instrumentation/vendors/datadog/listener.rb
125
- - lib/waterdrop/patches/rdkafka/bindings.rb
126
111
  - lib/waterdrop/patches/rdkafka/producer.rb
127
112
  - lib/waterdrop/producer.rb
128
113
  - lib/waterdrop/producer/async.rb
@@ -155,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
140
  - !ruby/object:Gem::Version
156
141
  version: '0'
157
142
  requirements: []
158
- rubygems_version: 3.3.7
143
+ rubygems_version: 3.3.26
159
144
  signing_key:
160
145
  specification_version: 4
161
146
  summary: Kafka messaging made easy!
metadata.gz.sig CHANGED
@@ -1,4 +1 @@
1
- A��ˣ�v=�o�*>�.C{YsbA,��aB��?#Ϻ��8\����wC�Ƈ��]%�S��Om�ȏY�u�vRm�l�a/����L��ӥ�J�����&����Ŷ{��a�&&Be�>b����}�}HiݞL��h�����IE��
2
- %�Z#�i��ޭ��P��%���A��%D"��۩u0lJ)��Yͦ��
3
- }"�"�9�� B�.��?��)�)yLY3{q��7�x��-�E��fE�xmg�c��b�7Ԗ&��kt�Dx�7f����AY�X�\R����#L�_�
4
- �*8/I���ȖskMo��?�_���A��\�V��&*>���ؼ�ң����_=�ry*�:�D�CD��\�������[0���I �6
1
+ ������H��[��� $��_Fm�˫����C?��bX�;��7FH��=�1s,�`F+m(Ƙ�}����H���g3��}�F�ʕlv�q��yV�=��`���u˦a�B3�S�?I�~A̺^�6��)!��=}l���(�?b�U��8 7�.���OgpyP�]���fCQ��PZ.� ����?~�%��|��m�\�����˃/�4#g�(=E�T$Q���I6`(,����&A��l��QD��p"��̏zJ:T0����q�<�B�<Jb��J��E��f}%)x{� ��#A�[v��j6�%�b1��o�㳾W�T�w�%k�g�Z�*
data/certs/mensfeld.pem DELETED
@@ -1,25 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhtYWNp
3
- ZWovREM9bWVuc2ZlbGQvREM9cGwwHhcNMjEwODExMTQxNTEzWhcNMjIwODExMTQx
4
- NTEzWjAjMSEwHwYDVQQDDBhtYWNpZWovREM9bWVuc2ZlbGQvREM9cGwwggGiMA0G
5
- CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDV2jKH4Ti87GM6nyT6D+ESzTI0MZDj
6
- ak2/TEwnxvijMJyCCPKT/qIkbW4/f0VHM4rhPr1nW73sb5SZBVFCLlJcOSKOBdUY
7
- TMY+SIXN2EtUaZuhAOe8LxtxjHTgRHvHcqUQMBENXTISNzCo32LnUxweu66ia4Pd
8
- 1mNRhzOqNv9YiBZvtBf7IMQ+sYdOCjboq2dlsWmJiwiDpY9lQBTnWORnT3mQxU5x
9
- vPSwnLB854cHdCS8fQo4DjeJBRZHhEbcE5sqhEMB3RZA3EtFVEXOxlNxVTS3tncI
10
- qyNXiWDaxcipaens4ObSY1C2HTV7OWb7OMqSCIybeYTSfkaSdqmcl4S6zxXkjH1J
11
- tnjayAVzD+QVXGijsPLE2PFnJAh9iDET2cMsjabO1f6l1OQNyAtqpcyQcgfnyW0z
12
- g7tGxTYD+6wJHffM9d9txOUw6djkF6bDxyqB8lo4Z3IObCx18AZjI9XPS9QG7w6q
13
- LCWuMG2lkCcRgASqaVk9fEf9yMc2xxz5o3kCAwEAAaN3MHUwCQYDVR0TBAIwADAL
14
- BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFBqUFCKCOe5IuueUVqOB991jyCLLMB0GA1Ud
15
- EQQWMBSBEm1hY2llakBtZW5zZmVsZC5wbDAdBgNVHRIEFjAUgRJtYWNpZWpAbWVu
16
- c2ZlbGQucGwwDQYJKoZIhvcNAQELBQADggGBADD0/UuTTFgW+CGk2U0RDw2RBOca
17
- W2LTF/G7AOzuzD0Tc4voc7WXyrgKwJREv8rgBimLnNlgmFJLmtUCh2U/MgxvcilH
18
- yshYcbseNvjkrtYnLRlWZR4SSB6Zei5AlyGVQLPkvdsBpNegcG6w075YEwzX/38a
19
- 8V9B/Yri2OGELBz8ykl7BsXUgNoUPA/4pHF6YRLz+VirOaUIQ4JfY7xGj6fSOWWz
20
- /rQ/d77r6o1mfJYM/3BRVg73a3b7DmRnE5qjwmSaSQ7u802pJnLesmArch0xGCT/
21
- fMmRli1Qb+6qOTl9mzD6UDMAyFR4t6MStLm0mIEqM0nBO5nUdUWbC7l9qXEf8XBE
22
- 2DP28p3EqSuS+lKbAWKcqv7t0iRhhmaod+Yn9mcrLN1sa3q3KSQ9BCyxezCD4Mk2
23
- R2P11bWoCtr70BsccVrN8jEhzwXngMyI2gVt750Y+dbTu1KgRqZKp/ECe7ZzPzXj
24
- pIy9vHxTANKYVyI4qj8OrFdEM5BQNu8oQpL0iQ==
25
- -----END CERTIFICATE-----
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WaterDrop
4
- module Instrumentation
5
- # This manager allows us to register multiple callbacks into a hook that is suppose to support
6
- # a single callback
7
- class CallbacksManager
8
- # @return [::WaterDrop::Instrumentation::CallbacksManager]
9
- def initialize
10
- @callbacks = Concurrent::Hash.new
11
- end
12
-
13
- # Invokes all the callbacks registered one after another
14
- #
15
- # @param args [Object] any args that should go to the callbacks
16
- # @note We do not use `#each_value` here on purpose. With it being used, we cannot dispatch
17
- # callbacks and add new at the same time. Since we don't know when and in what thread
18
- # things are going to be added to the manager, we need to extract values into an array and
19
- # run it. That way we can add new things the same time.
20
- def call(*args)
21
- @callbacks.values.each { |callback| callback.call(*args) }
22
- end
23
-
24
- # Adds a callback to the manager
25
- #
26
- # @param id [String] id of the callback (used when deleting it)
27
- # @param callable [#call] object that responds to a `#call` method
28
- def add(id, callable)
29
- @callbacks[id] = callable
30
- end
31
-
32
- # Removes the callback from the manager
33
- # @param id [String] id of the callback we want to remove
34
- def delete(id)
35
- @callbacks.delete(id)
36
- end
37
- end
38
- end
39
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WaterDrop
4
- # Namespace for all the things related with WaterDrop instrumentation process
5
- module Instrumentation
6
- class << self
7
- # Builds a manager for statistics callbacks
8
- # @return [WaterDrop::CallbacksManager]
9
- def statistics_callbacks
10
- @statistics_callbacks ||= CallbacksManager.new
11
- end
12
-
13
- # Builds a manager for error callbacks
14
- # @return [WaterDrop::CallbacksManager]
15
- def error_callbacks
16
- @error_callbacks ||= CallbacksManager.new
17
- end
18
- end
19
- end
20
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WaterDrop
4
- module Patches
5
- module Rdkafka
6
- # Extends `Rdkafka::Bindings` with some extra methods and updates callbacks that we intend
7
- # to work with in a bit different way than rdkafka itself
8
- module Bindings
9
- class << self
10
- # Add extra methods that we need
11
- # @param mod [::Rdkafka::Bindings] rdkafka bindings module
12
- def included(mod)
13
- mod.attach_function :rd_kafka_name, [:pointer], :string
14
-
15
- # Default rdkafka setup for errors doest not propagate client details, thus it always
16
- # publishes all the stuff for all rdkafka instances. We change that by providing
17
- # function that fetches the instance name, allowing us to have better notifications
18
- mod.send(:remove_const, :ErrorCallback)
19
- mod.const_set(:ErrorCallback, build_error_callback)
20
- end
21
-
22
- # @return [FFI::Function] overwritten callback function
23
- def build_error_callback
24
- FFI::Function.new(
25
- :void, %i[pointer int string pointer]
26
- ) do |client_prr, err_code, reason, _opaque|
27
- return nil unless ::Rdkafka::Config.error_callback
28
-
29
- name = ::Rdkafka::Bindings.rd_kafka_name(client_prr)
30
-
31
- error = ::Rdkafka::RdkafkaError.new(err_code, broker_message: reason)
32
-
33
- ::Rdkafka::Config.error_callback.call(name, error)
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
41
-
42
- ::Rdkafka::Bindings.include(::WaterDrop::Patches::Rdkafka::Bindings)