waterdrop 2.7.0.rc1 → 2.7.0

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: e715326d8ff0715491d71ec9f42c60eb049258a9b5eaf739a0b088cf515427dd
4
- data.tar.gz: ed94552c972a77b5509907f59910d9ad37f033b718666d5520335bbb7f5d545f
3
+ metadata.gz: 5308262b20199b02906783387f294a58beb01fa8850db3db19bb7be39395121a
4
+ data.tar.gz: d35c18c4b7352c20c8eeb623f54581476f108cb656912a571ef067cc796e884c
5
5
  SHA512:
6
- metadata.gz: 460c2e3f8989059293835af6f5a96c5c3af68a4f47608d98d22a217cfd15179edd8a834e8c621ff10ae894c5713878c833f23a6af47d83cfc215454326aabc37
7
- data.tar.gz: 67d497d37e6be9593dbe14bfb0d4df7d8c80c18f176dda66987a372acaffa68f172ae415d9797b713af0c67f6127113bd49a6ebb7a778eec4f8b69b864bceea7
6
+ metadata.gz: ac6693e44080e4edf9b201a5e735b283bb7fa81d36ae10bf0d7501faa00e5f099917144966beb7febc4b95c50ed78feb7c659e59753a78e4495111e3d00af322
7
+ data.tar.gz: 100439b79cc59bd668f40e4fed8086c49f13bfedebb68409981d8c70a39c692eb2b4f453d9a45c367f2612578b2c6ac8303bd56acdbbd27d3a02d5aab803d57a
checksums.yaml.gz.sig CHANGED
Binary file
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.0
1
+ 3.3.1
data/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # WaterDrop changelog
2
2
 
3
- ## 2.7.0 (Unreleased)
3
+ ## 2.7.0 (2024-04-26)
4
4
 
5
5
  This release contains **BREAKING** changes. Make sure to read and apply upgrade notes.
6
6
 
@@ -9,13 +9,34 @@ This release contains **BREAKING** changes. Make sure to read and apply upgrade
9
9
  - **[Breaking]** Change default timeouts so final delivery `message.timeout.ms` is less that `max_wait_time` so we do not end up with not final verdict.
10
10
  - **[Breaking]** Update all the time related configuration settings to be in `ms` and not mixed.
11
11
  - **[Breaking]** Remove no longer needed `wait_timeout` configuration option.
12
+ - **[Breaking]** Do **not** validate or morph (via middleware) messages added to the buffer prior to `flush_sync` or `flush_async`.
12
13
  - [Enhancement] Provide `WaterDrop::Producer#transaction?` that returns only when producer has an active transaction running.
13
14
  - [Enhancement] Introduce `instrument_on_wait_queue_full` flag (defaults to `true`) to be able to configure whether non critical (retryable) queue full errors should be instrumented in the error pipeline. Useful when building high-performance pipes with WaterDrop queue retry backoff as a throttler.
15
+ - [Enhancement] Protect critical `rdkafka` thread executable code sections.
16
+ - [Enhancement] Treat the queue size as a gauge rather than a cumulative stat (isturdy).
17
+ - [Fix] Fix a case where purge on non-initialized client would crash.
18
+ - [Fix] Middlewares run twice when using buffered produce.
19
+ - [Fix] Validations run twice when using buffered produce.
14
20
 
15
21
  ### Upgrade Notes
16
22
 
17
23
  **PLEASE MAKE SURE TO READ AND APPLY THEM!**
18
24
 
25
+ #### `wait_timeout` Configuration No Longer Needed
26
+
27
+ The `wait_timeout` WaterDrop configuration option is no longer needed. You can safely remove it.
28
+
29
+ ```ruby
30
+ producer = WaterDrop::Producer.new
31
+
32
+ producer.setup do |config|
33
+ # Other config...
34
+
35
+ # Remove this, no longer needed
36
+ config.wait_timeout = 30
37
+ end
38
+ ```
39
+
19
40
  #### Time Settings Format Alignment
20
41
 
21
42
  **All** time-related values are now configured in milliseconds instead of some being in seconds and some in milliseconds.
@@ -23,7 +44,6 @@ This release contains **BREAKING** changes. Make sure to read and apply upgrade
23
44
  The values that were changed from seconds to milliseconds are:
24
45
 
25
46
  - `max_wait_timeout`
26
- - `wait_timeout`
27
47
  - `wait_backoff_on_queue_full`
28
48
  - `wait_timeout_on_queue_full`
29
49
  - `wait_backoff_on_transaction_command, default`
@@ -37,10 +57,10 @@ producer.setup do |config|
37
57
  config.deliver = true
38
58
 
39
59
  # Replace this:
40
- config.wait_timeout = 30
60
+ config.max_wait_timeout = 30
41
61
 
42
62
  # With
43
- config.wait_timeout = 30_000
63
+ config.max_wait_timeout = 30_000
44
64
  # ...
45
65
  end
46
66
  ```
@@ -82,6 +102,32 @@ Below, you can find a table with what has changed, the new defaults, and the cur
82
102
 
83
103
  This alignment ensures that when using sync operations or invoking `#wait`, any exception you get should give you a conclusive and final delivery verdict.
84
104
 
105
+ #### Buffering No Longer Early Validates Messages
106
+
107
+ As of version `2.7.0`, WaterDrop has changed how message buffering works. Previously, messages underwent validation and middleware processing when they were buffered. Now, these steps are deferred until just before dispatching the messages. The buffer functions strictly as a thread-safe storage area without performing any validations or middleware operations until the messages are ready to be sent.
108
+
109
+ This adjustment was made primarily to ensure that middleware runs and validations are applied when most relevant—shortly before message dispatch. This approach addresses potential issues with buffers that might hold messages for extended periods:
110
+
111
+ - **Temporal Relevance**: Validating and processing messages near their dispatch time helps ensure that actions such as partition assignments reflect the current system state. This is crucial in dynamic environments where system states are subject to rapid changes.
112
+
113
+ - **Stale State Management**: By delaying validations and middleware to the dispatch phase, the system minimizes the risk of acting on outdated information, which could lead to incorrect processing or partitioning decisions.
114
+
115
+ ```ruby
116
+ # Prior to 2.7.0 this would raise an error
117
+ producer.buffer(topic: nil, payload: '')
118
+ # => WaterDrop::Errors::MessageInvalidError
119
+
120
+ # After 2.7.0 buffer will not, but flush_async will
121
+ producer.buffer(topic: nil, payload: '')
122
+ # => all good here
123
+ producer.flush_async(topic: nil, payload: '')
124
+ # => WaterDrop::Errors::MessageInvalidError
125
+ ```
126
+
127
+ #### Middleware Execution Prior to Flush When Buffering
128
+
129
+ The timing of middleware execution has been adjusted. Middleware, which was previously run when messages were added to the buffer, will now only execute immediately before the messages are flushed from the buffer and dispatched. This change is similar to the validation-related changes.
130
+
85
131
  ## 2.6.14 (2024-02-06)
86
132
  - [Enhancement] Instrument `producer.connected` and `producer.closing` lifecycle events.
87
133
 
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- waterdrop (2.7.0.rc1)
5
- karafka-core (>= 2.4.0.rc1, < 3.0.0)
4
+ waterdrop (2.7.0)
5
+ karafka-core (>= 2.4.0, < 3.0.0)
6
6
  zeitwerk (~> 2.3)
7
7
 
8
8
  GEM
@@ -31,16 +31,16 @@ GEM
31
31
  ffi (1.16.3)
32
32
  i18n (1.14.4)
33
33
  concurrent-ruby (~> 1.0)
34
- karafka-core (2.4.0.rc1)
35
- karafka-rdkafka (>= 0.15.0.rc1, < 0.16.0)
36
- karafka-rdkafka (0.15.0.rc1)
34
+ karafka-core (2.4.0)
35
+ karafka-rdkafka (>= 0.15.0, < 0.16.0)
36
+ karafka-rdkafka (0.15.0)
37
37
  ffi (~> 1.15)
38
38
  mini_portile2 (~> 2.6)
39
39
  rake (> 12)
40
- mini_portile2 (2.8.5)
40
+ mini_portile2 (2.8.6)
41
41
  minitest (5.22.3)
42
42
  mutex_m (0.2.0)
43
- rake (13.1.0)
43
+ rake (13.2.1)
44
44
  rspec (3.13.0)
45
45
  rspec-core (~> 3.13.0)
46
46
  rspec-expectations (~> 3.13.0)
@@ -76,4 +76,4 @@ DEPENDENCIES
76
76
  waterdrop!
77
77
 
78
78
  BUNDLED WITH
79
- 2.5.7
79
+ 2.5.9
data/docker-compose.yml CHANGED
@@ -3,7 +3,7 @@ version: '2'
3
3
  services:
4
4
  kafka:
5
5
  container_name: kafka
6
- image: confluentinc/cp-kafka:7.6.0
6
+ image: confluentinc/cp-kafka:7.6.1
7
7
 
8
8
  ports:
9
9
  - 9092:9092
@@ -44,6 +44,17 @@ module WaterDrop
44
44
  else
45
45
  instrument_error(delivery_report)
46
46
  end
47
+ # This runs from the rdkafka thread, thus we want to safe-guard it and prevent absolute
48
+ # crashes even if the instrumentation code fails. If it would bubble-up, it could crash
49
+ # the rdkafka background thread
50
+ rescue StandardError => e
51
+ @monitor.instrument(
52
+ 'error.occurred',
53
+ caller: self,
54
+ error: e,
55
+ producer_id: @producer_id,
56
+ type: 'callbacks.delivery.error'
57
+ )
47
58
  end
48
59
 
49
60
  private
@@ -32,6 +32,17 @@ module WaterDrop
32
32
  producer_id: @producer_id,
33
33
  type: 'librdkafka.error'
34
34
  )
35
+ # This runs from the rdkafka thread, thus we want to safe-guard it and prevent absolute
36
+ # crashes even if the instrumentation code fails. If it would bubble-up, it could crash
37
+ # the rdkafka background thread
38
+ rescue StandardError => e
39
+ @monitor.instrument(
40
+ 'error.occurred',
41
+ caller: self,
42
+ error: e,
43
+ producer_id: @producer_id,
44
+ type: 'callbacks.error.error'
45
+ )
35
46
  end
36
47
  end
37
48
  end
@@ -31,6 +31,17 @@ module WaterDrop
31
31
  bearer: @bearer,
32
32
  caller: self
33
33
  )
34
+ # This runs from the rdkafka thread, thus we want to safe-guard it and prevent absolute
35
+ # crashes even if the instrumentation code fails. If it would bubble-up, it could crash
36
+ # the rdkafka background thread
37
+ rescue StandardError => e
38
+ @monitor.instrument(
39
+ 'error.occurred',
40
+ caller: self,
41
+ error: e,
42
+ producer_id: @producer_id,
43
+ type: 'callbacks.oauthbearer_token_refresh.error'
44
+ )
34
45
  end
35
46
  end
36
47
  end
@@ -34,6 +34,17 @@ module WaterDrop
34
34
  producer_id: @producer_id,
35
35
  statistics: @statistics_decorator.call(statistics)
36
36
  )
37
+ # This runs from the rdkafka thread, thus we want to safe-guard it and prevent absolute
38
+ # crashes even if the instrumentation code fails. If it would bubble-up, it could crash
39
+ # the rdkafka background thread
40
+ rescue StandardError => e
41
+ @monitor.instrument(
42
+ 'error.occurred',
43
+ caller: self,
44
+ error: e,
45
+ producer_id: @producer_id,
46
+ type: 'callbacks.statistics.error'
47
+ )
37
48
  end
38
49
  end
39
50
  end
@@ -36,7 +36,7 @@ module WaterDrop
36
36
  setting :rd_kafka_metrics, default: [
37
37
  # Client metrics
38
38
  RdKafkaMetric.new(:count, :root, 'calls', 'tx_d'),
39
- RdKafkaMetric.new(:histogram, :root, 'queue.size', 'msg_cnt_d'),
39
+ RdKafkaMetric.new(:histogram, :root, 'queue.size', 'msg_cnt'),
40
40
 
41
41
  # Broker metrics
42
42
  RdKafkaMetric.new(:count, :brokers, 'deliver.attempts', 'txretries_d'),
@@ -12,9 +12,6 @@ module WaterDrop
12
12
  def buffer(message)
13
13
  ensure_active!
14
14
 
15
- message = middleware.run(message)
16
- validate_message!(message)
17
-
18
15
  @monitor.instrument(
19
16
  'message.buffered',
20
17
  producer_id: id,
@@ -32,9 +29,6 @@ module WaterDrop
32
29
  def buffer_many(messages)
33
30
  ensure_active!
34
31
 
35
- messages = middleware.run_many(messages)
36
- messages.each { |message| validate_message!(message) }
37
-
38
32
  @monitor.instrument(
39
33
  'messages.buffered',
40
34
  producer_id: id,
@@ -133,7 +133,12 @@ module WaterDrop
133
133
  @messages = []
134
134
  end
135
135
 
136
- @client.purge
136
+ # We should not purge if there is no client initialized
137
+ # It may not be initialized if we created a new producer that never connected to kafka,
138
+ # we used buffer and purged. In cases like this client won't exist
139
+ @connecting_mutex.synchronize do
140
+ @client&.purge
141
+ end
137
142
  end
138
143
  end
139
144
 
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '2.7.0.rc1'
6
+ VERSION = '2.7.0'
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.4.0.rc1', '< 3.0.0'
19
+ spec.add_dependency 'karafka-core', '>= 2.4.0', '< 3.0.0'
20
20
  spec.add_dependency 'zeitwerk', '~> 2.3'
21
21
 
22
22
  spec.required_ruby_version = '>= 3.0.0'
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.7.0.rc1
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -35,7 +35,7 @@ cert_chain:
35
35
  AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
36
36
  msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
37
37
  -----END CERTIFICATE-----
38
- date: 2024-04-10 00:00:00.000000000 Z
38
+ date: 2024-04-26 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.4.0.rc1
46
+ version: 2.4.0
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.4.0.rc1
56
+ version: 2.4.0
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
59
  version: 3.0.0
@@ -152,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
152
  - !ruby/object:Gem::Version
153
153
  version: '0'
154
154
  requirements: []
155
- rubygems_version: 3.5.3
155
+ rubygems_version: 3.5.9
156
156
  signing_key:
157
157
  specification_version: 4
158
158
  summary: Kafka messaging made easy!
metadata.gz.sig CHANGED
Binary file