waterdrop 2.8.15 → 2.8.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +215 -36
  3. data/.github/workflows/push.yml +3 -3
  4. data/.github/workflows/trigger-wiki-refresh.yml +1 -1
  5. data/.github/workflows/verify-action-pins.yml +1 -1
  6. data/.gitignore +0 -1
  7. data/.rubocop.yml +87 -0
  8. data/.ruby-version +1 -1
  9. data/.yard-lint.yml +172 -72
  10. data/CHANGELOG.md +9 -0
  11. data/Gemfile +8 -9
  12. data/Gemfile.lint +14 -0
  13. data/Gemfile.lint.lock +123 -0
  14. data/Gemfile.lock +27 -28
  15. data/README.md +1 -1
  16. data/Rakefile +2 -2
  17. data/bin/integrations +28 -29
  18. data/bin/verify_topics_naming +8 -8
  19. data/config/locales/errors.yml +12 -0
  20. data/docker-compose.oauth.yml +56 -0
  21. data/docker-compose.yml +1 -1
  22. data/lib/waterdrop/clients/dummy.rb +9 -0
  23. data/lib/waterdrop/clients/rdkafka.rb +13 -2
  24. data/lib/waterdrop/config.rb +32 -5
  25. data/lib/waterdrop/connection_pool.rb +13 -11
  26. data/lib/waterdrop/contracts/config.rb +30 -6
  27. data/lib/waterdrop/contracts/message.rb +2 -2
  28. data/lib/waterdrop/contracts/poller_config.rb +26 -0
  29. data/lib/waterdrop/contracts/transactional_offset.rb +2 -2
  30. data/lib/waterdrop/contracts/variant.rb +18 -18
  31. data/lib/waterdrop/errors.rb +3 -0
  32. data/lib/waterdrop/instrumentation/callbacks/delivery.rb +8 -8
  33. data/lib/waterdrop/instrumentation/callbacks/error.rb +5 -5
  34. data/lib/waterdrop/instrumentation/callbacks/oauthbearer_token_refresh.rb +4 -4
  35. data/lib/waterdrop/instrumentation/callbacks/statistics.rb +6 -6
  36. data/lib/waterdrop/instrumentation/idle_disconnector_listener.rb +4 -4
  37. data/lib/waterdrop/instrumentation/logger_listener.rb +10 -10
  38. data/lib/waterdrop/instrumentation/notifications.rb +3 -0
  39. data/lib/waterdrop/instrumentation/vendors/datadog/metrics_listener.rb +19 -19
  40. data/lib/waterdrop/polling/config.rb +52 -0
  41. data/lib/waterdrop/polling/latch.rb +49 -0
  42. data/lib/waterdrop/polling/poller.rb +415 -0
  43. data/lib/waterdrop/polling/queue_pipe.rb +63 -0
  44. data/lib/waterdrop/polling/state.rb +151 -0
  45. data/lib/waterdrop/polling.rb +22 -0
  46. data/lib/waterdrop/producer/async.rb +6 -6
  47. data/lib/waterdrop/producer/buffer.rb +8 -8
  48. data/lib/waterdrop/producer/idempotence.rb +3 -3
  49. data/lib/waterdrop/producer/sync.rb +15 -8
  50. data/lib/waterdrop/producer/testing.rb +1 -1
  51. data/lib/waterdrop/producer/transactions.rb +6 -6
  52. data/lib/waterdrop/producer.rb +113 -30
  53. data/lib/waterdrop/version.rb +1 -1
  54. data/lib/waterdrop.rb +15 -10
  55. data/package-lock.json +331 -0
  56. data/package.json +9 -0
  57. data/renovate.json +25 -6
  58. data/waterdrop.gemspec +23 -23
  59. metadata +17 -5
  60. data/.coditsu/ci.yml +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e65e5de3fde4fee519f6c7313c832e13deffbaf745e7fa934d419db1d4cd050
4
- data.tar.gz: de1eeaefdff74ce517e15607d7015886211d831d8a2045d40b782edc1d68fe8b
3
+ metadata.gz: 37640abb3da7c77152964c699b1fc0426b6ebf57f82aa5e0175498409bf10aff
4
+ data.tar.gz: 1b30de7a05e720890f94e1aef028886140b9a7faa4c67c80faa4a4abbbeba002
5
5
  SHA512:
6
- metadata.gz: 9f25c8a5468682bd6bb90ea342557fe1671831598ffa8761af34abbbc58f4cecf682ad682fb2395125e524a571e32802ed16d01139651e3e7584fd3fa671c67a
7
- data.tar.gz: 863a9b02697708b8aadf52cd86fcee2b42ea1ca4c9c44ab7a2468e2ca0e1c5c76b391ae6d4e2eea63a77d67dd0ed33fc10d3d097b27f73cb47d174f3b93becd7
6
+ metadata.gz: f3b79f8f1aba96c578ec367a286a9ec4e3fac0f20d5d07e05e417c6e7a0553117a18586db5546240df69d6b2455badab1e93558d10c842ea28377691a074dc45
7
+ data.tar.gz: df6c34c35b7a51f5f4c307809e604d4cd142e4bf6b77158f8e31a9b761cffdf59a130d71474afd8b1efa6c183468a13b01b4f4df877d9e23a5dbbb19352b86ce
@@ -17,37 +17,31 @@ jobs:
17
17
  specs:
18
18
  timeout-minutes: 15
19
19
  runs-on: ubuntu-latest
20
- env:
21
- BUNDLE_FORCE_RUBY_PLATFORM: ${{ matrix.force_ruby_platform }}
22
20
  strategy:
23
21
  fail-fast: false
24
22
  matrix:
25
23
  ruby:
26
- - '4.0.0-preview2'
24
+ - '4.0'
27
25
  - '3.4'
28
26
  - '3.3'
29
27
  - '3.2'
30
- force_ruby_platform:
31
- - true
32
- - false
28
+ polling_mode:
29
+ - 'thread'
30
+ - 'fiber'
33
31
  include:
34
32
  - ruby: '3.4'
33
+ polling_mode: 'thread'
35
34
  coverage: 'true'
36
35
  steps:
37
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
36
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
38
37
  with:
39
38
  fetch-depth: 0
40
39
 
41
40
  - name: Install package dependencies
42
41
  run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
43
42
 
44
- - name: Remove platform-specific ffi entries for Ruby previews
45
- if: contains(matrix.ruby, 'preview')
46
- run: |
47
- sed -i '/^\s*ffi (.*-.*)$/d' Gemfile.lock
48
-
49
43
  - name: Set up Ruby
50
- uses: ruby/setup-ruby@8aeb6ff8030dd539317f8e1769a044873b56ea71 # v1.268.0
44
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
51
45
  with:
52
46
  ruby-version: ${{matrix.ruby}}
53
47
  bundler-cache: true
@@ -75,10 +69,14 @@ jobs:
75
69
  - name: Run all tests
76
70
  env:
77
71
  GITHUB_COVERAGE: ${{matrix.coverage}}
72
+ FD_POLLING: ${{ matrix.polling_mode == 'fiber' && 'true' || 'false' }}
78
73
  run: bundle exec rspec
79
74
 
80
75
  - name: Run integration tests
81
- run: ./bin/integrations
76
+ env:
77
+ FD_POLLING: ${{ matrix.polling_mode == 'fiber' && 'true' || 'false' }}
78
+ # Exclude oauth_token_refresh - requires separate Keycloak + OAuth Kafka infrastructure
79
+ run: ./bin/integrations --exclude oauth_token_refresh
82
80
 
83
81
  - name: Check Kafka logs for unexpected warnings
84
82
  run: bin/verify_kafka_warnings
@@ -86,53 +84,234 @@ jobs:
86
84
  - name: Check test topics naming convention
87
85
  run: bin/verify_topics_naming
88
86
 
89
- coditsu:
87
+ rubocop:
90
88
  timeout-minutes: 5
91
89
  runs-on: ubuntu-latest
92
- strategy:
93
- fail-fast: false
90
+ env:
91
+ BUNDLE_GEMFILE: Gemfile.lint
94
92
  steps:
95
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
93
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
96
94
  with:
97
95
  fetch-depth: 0
98
- - name: Download Coditsu script
99
- run: |
100
- curl -sSL https://api.coditsu.io/run/ci -o coditsu_script.sh
101
- chmod +x coditsu_script.sh
102
- - name: Verify Coditsu script checksum
103
- run: |
104
- EXPECTED_SHA256="0aecc5aa010f53fca264548a41467a2b0a1208d750ce1da3e98a217304cacbbc"
105
- ACTUAL_SHA256=$(sha256sum coditsu_script.sh | awk '{ print $1 }')
106
- if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
107
- echo "::error::Checksum verification failed. Expected $EXPECTED_SHA256 but got $ACTUAL_SHA256."
108
- exit 1
109
- fi
110
- - name: Run Coditsu
111
- run: ./coditsu_script.sh
96
+ - name: Set up Ruby
97
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
98
+ with:
99
+ ruby-version: '4.0.1'
100
+ bundler-cache: true
101
+ - name: Run rubocop
102
+ run: bundle exec rubocop
112
103
 
113
104
  yard-lint:
114
105
  timeout-minutes: 5
115
106
  runs-on: ubuntu-latest
107
+ env:
108
+ BUNDLE_GEMFILE: Gemfile.lint
116
109
  steps:
117
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
110
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
118
111
  with:
119
112
  fetch-depth: 0
120
113
  - name: Set up Ruby
121
- uses: ruby/setup-ruby@8aeb6ff8030dd539317f8e1769a044873b56ea71 # v1.268.0
114
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
122
115
  with:
123
- ruby-version: '3.4'
116
+ ruby-version: '4.0.1'
124
117
  bundler-cache: true
125
118
  - name: Run yard-lint
126
119
  run: bundle exec yard-lint lib/
127
120
 
121
+ lostconf:
122
+ timeout-minutes: 5
123
+ runs-on: ubuntu-latest
124
+ steps:
125
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
126
+ with:
127
+ fetch-depth: 0
128
+ - name: Set up Node.js
129
+ uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
130
+ with:
131
+ node-version: '20'
132
+ cache: 'npm'
133
+ - name: Install dependencies
134
+ run: npm ci
135
+ - name: Run lostconf
136
+ run: npx lostconf --fail-on-stale
137
+
138
+ oauth-integration:
139
+ timeout-minutes: 10
140
+ runs-on: ubuntu-latest
141
+ strategy:
142
+ fail-fast: false
143
+ matrix:
144
+ polling_mode:
145
+ - 'thread'
146
+ - 'fiber'
147
+ steps:
148
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
149
+ with:
150
+ fetch-depth: 0
151
+
152
+ - name: Set up Ruby
153
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
154
+ with:
155
+ ruby-version: '4.0.1'
156
+ bundler-cache: true
157
+ bundler: 'latest'
158
+
159
+ - name: Start OAuth infrastructure (Keycloak + Kafka with SASL/OAUTHBEARER)
160
+ run: docker compose -f docker-compose.oauth.yml up -d
161
+
162
+ - name: Wait for Keycloak to be ready
163
+ run: |
164
+ echo "Waiting for Keycloak to be ready..."
165
+ for i in {1..60}; do
166
+ if curl -sf http://localhost:8080/realms/kafka > /dev/null 2>&1; then
167
+ echo "Keycloak is ready!"
168
+ break
169
+ fi
170
+ echo "Waiting... ($i/60)"
171
+ sleep 2
172
+ done
173
+
174
+ - name: Wait for Kafka OAuth broker to be ready
175
+ run: |
176
+ echo "Waiting for Kafka OAuth broker..."
177
+ sleep 10
178
+
179
+ - name: Install dependencies
180
+ run: |
181
+ gem install bundler --no-document
182
+ bundle config set without 'tools benchmarks docs development'
183
+ bundle install --jobs 4 --retry 3
184
+
185
+ - name: Run OAuth integration test
186
+ env:
187
+ FD_POLLING: ${{ matrix.polling_mode == 'fiber' && 'true' || 'false' }}
188
+ run: ./bin/integrations oauth_token_refresh
189
+
190
+ - name: Show Keycloak logs on failure
191
+ if: failure()
192
+ run: docker compose -f docker-compose.oauth.yml logs keycloak
193
+
194
+ - name: Show Kafka OAuth logs on failure
195
+ if: failure()
196
+ run: docker compose -f docker-compose.oauth.yml logs kafka-oauth
197
+
198
+ specs-macos:
199
+ timeout-minutes: 30
200
+ runs-on: macos-15
201
+ env:
202
+ CONFLUENT_VERSION: "8.0.0"
203
+ strategy:
204
+ fail-fast: false
205
+ matrix:
206
+ polling_mode:
207
+ - 'thread'
208
+ - 'fiber'
209
+ steps:
210
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
211
+ with:
212
+ fetch-depth: 0
213
+
214
+ - name: Install Bash 4+
215
+ run: |
216
+ brew install bash
217
+ echo "/opt/homebrew/bin" >> $GITHUB_PATH
218
+
219
+ - name: Set up Ruby
220
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
221
+ with:
222
+ ruby-version: '4.0.1'
223
+ bundler-cache: true
224
+ bundler: 'latest'
225
+
226
+ - name: Install and Start Confluent Community Kafka (KRaft)
227
+ run: |
228
+ brew install openjdk@17
229
+ export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH"
230
+ export JAVA_HOME="/opt/homebrew/opt/openjdk@17"
231
+
232
+ curl -O "https://packages.confluent.io/archive/8.0/confluent-community-${CONFLUENT_VERSION}.tar.gz"
233
+ tar -xzf "confluent-community-${CONFLUENT_VERSION}.tar.gz"
234
+
235
+ export CONFLUENT_HOME="$(pwd)/confluent-${CONFLUENT_VERSION}"
236
+ export PATH="$CONFLUENT_HOME/bin:$PATH"
237
+ cd "$CONFLUENT_HOME"
238
+
239
+ KRAFT_CONFIG=""
240
+ for config in "etc/kafka/kraft/server.properties" "config/kraft/server.properties" "etc/kafka/server.properties"; do
241
+ if [ -f "$config" ]; then
242
+ KRAFT_CONFIG="$config"
243
+ echo "Found config: $KRAFT_CONFIG"
244
+ break
245
+ fi
246
+ done
247
+
248
+ if [ -z "$KRAFT_CONFIG" ]; then
249
+ echo "❌ No server config found"
250
+ exit 1
251
+ fi
252
+
253
+ cat >> "$KRAFT_CONFIG" << 'EOF'
254
+
255
+ process.roles=broker,controller
256
+ node.id=1
257
+ controller.quorum.voters=1@127.0.0.1:9093
258
+ listeners=PLAINTEXT://127.0.0.1:9092,CONTROLLER://127.0.0.1:9093
259
+ advertised.listeners=PLAINTEXT://127.0.0.1:9092
260
+ controller.listener.names=CONTROLLER
261
+ inter.broker.listener.name=PLAINTEXT
262
+ log.dirs=/tmp/kraft-combined-logs
263
+ authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
264
+ super.users=User:ANONYMOUS
265
+ allow.everyone.if.no.acl.found=true
266
+ EOF
267
+
268
+ CLUSTER_ID=$(bin/kafka-storage random-uuid)
269
+ bin/kafka-storage format -t "$CLUSTER_ID" -c "$KRAFT_CONFIG"
270
+ bin/kafka-server-start "$KRAFT_CONFIG" &
271
+
272
+ sleep 20
273
+
274
+ for i in {1..30}; do
275
+ if bin/kafka-topics --bootstrap-server 127.0.0.1:9092 --list >/dev/null 2>&1; then
276
+ echo "✅ Confluent Community ${CONFLUENT_VERSION} (KRaft) is ready!"
277
+ break
278
+ fi
279
+ [ $i -eq 30 ] && { echo "❌ Kafka failed to start"; exit 1; }
280
+ sleep 2
281
+ done
282
+
283
+ - name: Install latest bundler
284
+ run: |
285
+ gem install bundler --no-document
286
+ gem update --system --no-document
287
+ bundle config set without 'tools benchmarks docs'
288
+
289
+ - name: Bundle install
290
+ run: |
291
+ bundle config set without development
292
+ bundle install --jobs 4 --retry 3
293
+
294
+ - name: Run all tests
295
+ env:
296
+ FD_POLLING: ${{ matrix.polling_mode == 'fiber' && 'true' || 'false' }}
297
+ run: bundle exec rspec
298
+
299
+ - name: Run integration tests
300
+ env:
301
+ FD_POLLING: ${{ matrix.polling_mode == 'fiber' && 'true' || 'false' }}
302
+ run: ./bin/integrations --exclude oauth_token_refresh
303
+
128
304
  ci-success:
129
305
  name: CI Success
130
306
  runs-on: ubuntu-latest
131
307
  if: always()
132
308
  needs:
133
- - coditsu
309
+ - rubocop
134
310
  - specs
311
+ - specs-macos
135
312
  - yard-lint
313
+ - lostconf
314
+ - oauth-integration
136
315
  steps:
137
316
  - name: Check all jobs passed
138
317
  if: |
@@ -19,12 +19,12 @@ jobs:
19
19
  id-token: write
20
20
 
21
21
  steps:
22
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
22
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23
23
  with:
24
24
  fetch-depth: 0
25
25
 
26
26
  - name: Set up Ruby
27
- uses: ruby/setup-ruby@2a7b30092b0caf9c046252510f9273b4875f3db9 # v1.254.0
27
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
28
28
  with:
29
29
  bundler-cache: false
30
30
 
@@ -32,4 +32,4 @@ jobs:
32
32
  run: |
33
33
  bundle install --jobs 4 --retry 3
34
34
 
35
- - uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1
35
+ - uses: rubygems/release-gem@1c162a739e8b4cb21a676e97b087e8268d8fc40b # v1.1.2
@@ -13,7 +13,7 @@ jobs:
13
13
  if: github.repository_owner == 'karafka'
14
14
  steps:
15
15
  - name: Trigger wiki refresh
16
- uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0
16
+ uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
17
17
  with:
18
18
  token: ${{ secrets.WIKI_REPO_TOKEN }}
19
19
  repository: karafka/wiki
@@ -7,7 +7,7 @@ jobs:
7
7
  verify_action_pins:
8
8
  runs-on: ubuntu-latest
9
9
  steps:
10
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
10
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
11
11
  - name: Check SHA pins
12
12
  run: |
13
13
  if grep -E -r "uses: .*/.*@(v[0-9]+|main|master)($|[[:space:]]|$)" --include="*.yml" --include="*.yaml" .github/workflows/ | grep -v "#"; then
data/.gitignore CHANGED
@@ -12,7 +12,6 @@ db/*.sqlite3
12
12
  /tmp/*
13
13
  *.gem
14
14
  *.~
15
- /.coditsu/local.yml
16
15
  .byebug_history
17
16
 
18
17
  # various artifacts
data/.rubocop.yml ADDED
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ plugins:
4
+ - rubocop-capybara
5
+ - rubocop-factory_bot
6
+ - rubocop-performance
7
+ - rubocop-rspec
8
+ - rubocop-rspec_rails
9
+ - rubocop-thread_safety
10
+
11
+ inherit_gem:
12
+ standard: config/base.yml
13
+ standard-performance: config/base.yml
14
+ standard-rspec: config/base.yml
15
+
16
+ AllCops:
17
+ NewCops: enable
18
+ TargetRubyVersion: 3.2
19
+ Include:
20
+ - "**/*.rb"
21
+ - "**/*.gemspec"
22
+ - "**/Gemfile"
23
+ - "**/Rakefile"
24
+ - Gemfile.lint
25
+
26
+ # Disabled departments - not a Rails project, no Capybara/FactoryBot
27
+ Capybara:
28
+ Enabled: false
29
+
30
+ FactoryBot:
31
+ Enabled: false
32
+
33
+ RSpecRails:
34
+ Enabled: false
35
+
36
+ # Layout
37
+ Layout/LineLength:
38
+ Max: 100
39
+
40
+ Layout/SpaceInsideHashLiteralBraces:
41
+ EnforcedStyle: space
42
+
43
+ # Lint
44
+ Lint/RescueException:
45
+ Exclude:
46
+ - lib/waterdrop/producer/transactions.rb
47
+
48
+ # RSpec
49
+ RSpec:
50
+ Exclude:
51
+ - spec/integrations/**/*
52
+
53
+ RSpec/ExampleLength:
54
+ Enabled: false
55
+
56
+ RSpec/IndexedLet:
57
+ Enabled: false
58
+
59
+ RSpec/MultipleExpectations:
60
+ Enabled: false
61
+
62
+ RSpec/MultipleMemoizedHelpers:
63
+ Max: 20
64
+
65
+ RSpec/NestedGroups:
66
+ Max: 4
67
+
68
+ RSpec/NoExpectationExample:
69
+ Enabled: false
70
+
71
+ RSpec/SpecFilePathFormat:
72
+ Enabled: false
73
+
74
+ # Style
75
+ Style/SlicingWithRange:
76
+ Exclude:
77
+ - bin/integrations
78
+
79
+ # ThreadSafety
80
+ ThreadSafety/ClassAndModuleAttributes:
81
+ Enabled: false
82
+
83
+ ThreadSafety/ClassInstanceVariable:
84
+ Enabled: false
85
+
86
+ ThreadSafety/NewThread:
87
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.4.5
1
+ 4.0.1