karafka-rdkafka 0.20.0.rc5-arm64-darwin → 0.21.0-arm64-darwin
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.
- checksums.yaml +4 -4
- data/.github/workflows/{ci_linux_x86_64_musl.yml → ci_linux_alpine_x86_64_musl.yml} +63 -71
- data/.github/workflows/ci_linux_alpine_x86_64_musl_complementary.yml +264 -0
- data/.github/workflows/ci_linux_debian_x86_64_gnu.yml +271 -0
- data/.github/workflows/ci_linux_debian_x86_64_gnu_complementary.yml +334 -0
- data/.github/workflows/{ci_linux_x86_64_gnu.yml → ci_linux_ubuntu_aarch64_gnu.yml} +78 -56
- data/.github/workflows/ci_linux_ubuntu_aarch64_gnu_complementary.yml +295 -0
- data/.github/workflows/ci_linux_ubuntu_x86_64_gnu.yml +281 -0
- data/.github/workflows/ci_linux_ubuntu_x86_64_gnu_complementary.yml +294 -0
- data/.github/workflows/ci_macos_arm64.yml +28 -50
- data/.github/workflows/push_linux_aarch64_gnu.yml +65 -0
- data/.github/workflows/push_linux_x86_64_gnu.yml +4 -3
- data/.github/workflows/push_linux_x86_64_musl.yml +6 -4
- data/.github/workflows/push_macos_arm64.yml +3 -3
- data/.github/workflows/push_ruby.yml +1 -1
- data/.github/workflows/trigger-wiki-refresh.yml +30 -0
- data/.github/workflows/verify-action-pins.yml +1 -1
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +18 -2
- data/README.md +48 -147
- data/dist/cyrus-sasl-2.1.28.tar.gz +0 -0
- data/dist/krb5-1.21.3.tar.gz +0 -0
- data/dist/openssl-3.0.16.tar.gz +0 -0
- data/dist/zlib-1.3.1.tar.gz +0 -0
- data/dist/zstd-1.5.7.tar.gz +0 -0
- data/docker-compose-ssl.yml +35 -0
- data/ext/build_common.sh +18 -3
- data/ext/build_linux_aarch64_gnu.sh +326 -0
- data/ext/build_linux_x86_64_gnu.sh +17 -6
- data/ext/build_linux_x86_64_musl.sh +18 -8
- data/ext/build_macos_arm64.sh +7 -0
- data/ext/generate-ssl-certs.sh +109 -0
- data/ext/librdkafka.dylib +0 -0
- data/karafka-rdkafka.gemspec +3 -1
- data/lib/rdkafka/bindings.rb +6 -8
- data/lib/rdkafka/config.rb +1 -4
- data/lib/rdkafka/consumer.rb +1 -1
- data/lib/rdkafka/producer.rb +11 -6
- data/lib/rdkafka/version.rb +3 -3
- data/spec/integrations/ssl_stress_spec.rb +121 -0
- data/spec/{rdkafka → lib/rdkafka}/admin_spec.rb +219 -6
- data/spec/{rdkafka → lib/rdkafka}/bindings_spec.rb +0 -24
- data/spec/{rdkafka → lib/rdkafka}/config_spec.rb +1 -1
- data/spec/{rdkafka → lib/rdkafka}/consumer_spec.rb +50 -6
- data/spec/{rdkafka → lib/rdkafka}/metadata_spec.rb +2 -2
- data/spec/{rdkafka → lib/rdkafka}/producer/delivery_report_spec.rb +1 -1
- data/spec/{rdkafka → lib/rdkafka}/producer_spec.rb +301 -8
- data/spec/spec_helper.rb +65 -16
- metadata +87 -43
- data/spec/rdkafka/producer/partitions_count_spec.rb +0 -359
- /data/spec/{rdkafka → lib/rdkafka}/abstract_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/create_acl_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/create_acl_report_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/create_topic_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/create_topic_report_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/delete_acl_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/delete_acl_report_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/delete_topic_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/delete_topic_report_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/describe_acl_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/admin/describe_acl_report_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/callbacks_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/consumer/headers_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/consumer/message_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/consumer/partition_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/consumer/topic_partition_list_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/error_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/native_kafka_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/producer/delivery_handle_spec.rb +0 -0
- /data/spec/{rdkafka → lib/rdkafka}/producer/partitions_count_cache_spec.rb +0 -0
@@ -263,8 +263,6 @@ describe Rdkafka::Producer do
|
|
263
263
|
expect(message.partition).to eq 1
|
264
264
|
expect(message.payload).to eq "payload"
|
265
265
|
expect(message.key).to eq "key"
|
266
|
-
# Since api.version.request is on by default we will get
|
267
|
-
# the message creation timestamp if it's not set.
|
268
266
|
expect(message.timestamp).to be_within(10).of(Time.now)
|
269
267
|
end
|
270
268
|
|
@@ -340,7 +338,7 @@ describe Rdkafka::Producer do
|
|
340
338
|
)
|
341
339
|
end
|
342
340
|
|
343
|
-
expect(messages[0].partition).to
|
341
|
+
expect(messages[0].partition).to be >= 0
|
344
342
|
expect(messages[0].key).to eq 'a'
|
345
343
|
end
|
346
344
|
|
@@ -665,7 +663,7 @@ describe Rdkafka::Producer do
|
|
665
663
|
context "when not being able to deliver the message" do
|
666
664
|
let(:producer) do
|
667
665
|
rdkafka_producer_config(
|
668
|
-
"bootstrap.servers": "127.0.0.1:
|
666
|
+
"bootstrap.servers": "127.0.0.1:9095",
|
669
667
|
"message.timeout.ms": 100
|
670
668
|
).producer
|
671
669
|
end
|
@@ -781,14 +779,15 @@ describe Rdkafka::Producer do
|
|
781
779
|
context 'when it cannot flush due to a timeout' do
|
782
780
|
let(:producer) do
|
783
781
|
rdkafka_producer_config(
|
784
|
-
"bootstrap.servers": "127.0.0.1:
|
782
|
+
"bootstrap.servers": "127.0.0.1:9095",
|
785
783
|
"message.timeout.ms": 2_000
|
786
784
|
).producer
|
787
785
|
end
|
788
786
|
|
789
787
|
after do
|
790
788
|
# Allow rdkafka to evict message preventing memory-leak
|
791
|
-
|
789
|
+
# We give it a bit more time as on slow CIs things take time
|
790
|
+
sleep(5)
|
792
791
|
end
|
793
792
|
|
794
793
|
it "should return false on flush when cannot deliver and beyond timeout" do
|
@@ -828,7 +827,7 @@ describe Rdkafka::Producer do
|
|
828
827
|
context 'when there are outgoing things in the queue' do
|
829
828
|
let(:producer) do
|
830
829
|
rdkafka_producer_config(
|
831
|
-
"bootstrap.servers": "127.0.0.1:
|
830
|
+
"bootstrap.servers": "127.0.0.1:9095",
|
832
831
|
"message.timeout.ms": 2_000
|
833
832
|
).producer
|
834
833
|
end
|
@@ -864,7 +863,7 @@ describe Rdkafka::Producer do
|
|
864
863
|
before { producer.delivery_callback = delivery_callback }
|
865
864
|
|
866
865
|
it "should run the callback" do
|
867
|
-
|
866
|
+
producer.produce(
|
868
867
|
topic: "produce_test_topic",
|
869
868
|
payload: "payload headers"
|
870
869
|
)
|
@@ -1231,4 +1230,298 @@ describe Rdkafka::Producer do
|
|
1231
1230
|
end
|
1232
1231
|
end
|
1233
1232
|
end
|
1233
|
+
|
1234
|
+
let(:producer) { rdkafka_producer_config.producer }
|
1235
|
+
let(:all_partitioners) { %w(random consistent consistent_random murmur2 murmur2_random fnv1a fnv1a_random) }
|
1236
|
+
|
1237
|
+
describe "partitioner behavior through producer API" do
|
1238
|
+
context "testing all partitioners with same key" do
|
1239
|
+
it "should not return partition 0 for all partitioners" do
|
1240
|
+
test_key = "test-key-123"
|
1241
|
+
results = {}
|
1242
|
+
|
1243
|
+
all_partitioners.each do |partitioner|
|
1244
|
+
handle = producer.produce(
|
1245
|
+
topic: "partitioner_test_topic",
|
1246
|
+
payload: "test payload",
|
1247
|
+
partition_key: test_key,
|
1248
|
+
partitioner: partitioner
|
1249
|
+
)
|
1250
|
+
|
1251
|
+
report = handle.wait(max_wait_timeout: 5)
|
1252
|
+
results[partitioner] = report.partition
|
1253
|
+
end
|
1254
|
+
|
1255
|
+
# Should not all be the same partition (especially not all 0)
|
1256
|
+
unique_partitions = results.values.uniq
|
1257
|
+
expect(unique_partitions.size).to be > 1
|
1258
|
+
end
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
context "empty string partition key" do
|
1262
|
+
it "should produce message with empty partition key without crashing and go to partition 0 for all partitioners" do
|
1263
|
+
all_partitioners.each do |partitioner|
|
1264
|
+
handle = producer.produce(
|
1265
|
+
topic: "partitioner_test_topic",
|
1266
|
+
payload: "test payload",
|
1267
|
+
key: "test-key",
|
1268
|
+
partition_key: "",
|
1269
|
+
partitioner: partitioner
|
1270
|
+
)
|
1271
|
+
|
1272
|
+
report = handle.wait(max_wait_timeout: 5)
|
1273
|
+
expect(report.partition).to be >= 0
|
1274
|
+
end
|
1275
|
+
end
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
context "nil partition key" do
|
1279
|
+
it "should handle nil partition key gracefully" do
|
1280
|
+
handle = producer.produce(
|
1281
|
+
topic: "partitioner_test_topic",
|
1282
|
+
payload: "test payload",
|
1283
|
+
key: "test-key",
|
1284
|
+
partition_key: nil
|
1285
|
+
)
|
1286
|
+
|
1287
|
+
report = handle.wait(max_wait_timeout: 5)
|
1288
|
+
expect(report.partition).to be >= 0
|
1289
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1290
|
+
end
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
context "various key types and lengths with different partitioners" do
|
1294
|
+
it "should handle very short keys with all partitioners" do
|
1295
|
+
all_partitioners.each do |partitioner|
|
1296
|
+
handle = producer.produce(
|
1297
|
+
topic: "partitioner_test_topic",
|
1298
|
+
payload: "test payload",
|
1299
|
+
partition_key: "a",
|
1300
|
+
partitioner: partitioner
|
1301
|
+
)
|
1302
|
+
|
1303
|
+
report = handle.wait(max_wait_timeout: 5)
|
1304
|
+
expect(report.partition).to be >= 0
|
1305
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1306
|
+
end
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
it "should handle very long keys with all partitioners" do
|
1310
|
+
long_key = "a" * 1000
|
1311
|
+
|
1312
|
+
all_partitioners.each do |partitioner|
|
1313
|
+
handle = producer.produce(
|
1314
|
+
topic: "partitioner_test_topic",
|
1315
|
+
payload: "test payload",
|
1316
|
+
partition_key: long_key,
|
1317
|
+
partitioner: partitioner
|
1318
|
+
)
|
1319
|
+
|
1320
|
+
report = handle.wait(max_wait_timeout: 5)
|
1321
|
+
expect(report.partition).to be >= 0
|
1322
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1323
|
+
end
|
1324
|
+
end
|
1325
|
+
|
1326
|
+
it "should handle unicode keys with all partitioners" do
|
1327
|
+
unicode_key = "测试键值🚀"
|
1328
|
+
|
1329
|
+
all_partitioners.each do |partitioner|
|
1330
|
+
handle = producer.produce(
|
1331
|
+
topic: "partitioner_test_topic",
|
1332
|
+
payload: "test payload",
|
1333
|
+
partition_key: unicode_key,
|
1334
|
+
partitioner: partitioner
|
1335
|
+
)
|
1336
|
+
|
1337
|
+
report = handle.wait(max_wait_timeout: 5)
|
1338
|
+
expect(report.partition).to be >= 0
|
1339
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1340
|
+
end
|
1341
|
+
end
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
context "consistency testing for deterministic partitioners" do
|
1345
|
+
%w(consistent murmur2 fnv1a).each do |partitioner|
|
1346
|
+
it "should consistently route same partition key to same partition with #{partitioner}" do
|
1347
|
+
partition_key = "consistent-test-key"
|
1348
|
+
|
1349
|
+
# Produce multiple messages with same partition key
|
1350
|
+
reports = 5.times.map do
|
1351
|
+
handle = producer.produce(
|
1352
|
+
topic: "partitioner_test_topic",
|
1353
|
+
payload: "test payload #{Time.now.to_f}",
|
1354
|
+
partition_key: partition_key,
|
1355
|
+
partitioner: partitioner
|
1356
|
+
)
|
1357
|
+
handle.wait(max_wait_timeout: 5)
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
# All should go to same partition
|
1361
|
+
partitions = reports.map(&:partition).uniq
|
1362
|
+
expect(partitions.size).to eq(1)
|
1363
|
+
end
|
1364
|
+
end
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
context "randomness testing for random partitioners" do
|
1368
|
+
%w(random consistent_random murmur2_random fnv1a_random).each do |partitioner|
|
1369
|
+
it "should potentially distribute across partitions with #{partitioner}" do
|
1370
|
+
# Note: random partitioners might still return same value by chance
|
1371
|
+
partition_key = "random-test-key"
|
1372
|
+
|
1373
|
+
reports = 10.times.map do
|
1374
|
+
handle = producer.produce(
|
1375
|
+
topic: "partitioner_test_topic",
|
1376
|
+
payload: "test payload #{Time.now.to_f}",
|
1377
|
+
partition_key: partition_key,
|
1378
|
+
partitioner: partitioner
|
1379
|
+
)
|
1380
|
+
handle.wait(max_wait_timeout: 5)
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
partitions = reports.map(&:partition)
|
1384
|
+
|
1385
|
+
# Just ensure they're valid partitions
|
1386
|
+
partitions.each do |partition|
|
1387
|
+
expect(partition).to be >= 0
|
1388
|
+
expect(partition).to be < producer.partition_count("partitioner_test_topic")
|
1389
|
+
end
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
context "comparing different partitioners with same key" do
|
1395
|
+
it "should route different partition keys to potentially different partitions" do
|
1396
|
+
keys = ["key1", "key2", "key3", "key4", "key5"]
|
1397
|
+
|
1398
|
+
all_partitioners.each do |partitioner|
|
1399
|
+
reports = keys.map do |key|
|
1400
|
+
handle = producer.produce(
|
1401
|
+
topic: "partitioner_test_topic",
|
1402
|
+
payload: "test payload",
|
1403
|
+
partition_key: key,
|
1404
|
+
partitioner: partitioner
|
1405
|
+
)
|
1406
|
+
handle.wait(max_wait_timeout: 5)
|
1407
|
+
end
|
1408
|
+
|
1409
|
+
partitions = reports.map(&:partition).uniq
|
1410
|
+
|
1411
|
+
# Should distribute across multiple partitions for most partitioners
|
1412
|
+
# (though some might hash all keys to same partition by chance)
|
1413
|
+
expect(partitions.all? { |p| p >= 0 && p < producer.partition_count("partitioner_test_topic") }).to be true
|
1414
|
+
end
|
1415
|
+
end
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
context "partition key vs regular key behavior" do
|
1419
|
+
it "should use partition key for partitioning when both key and partition_key are provided" do
|
1420
|
+
# Use keys that would hash to different partitions
|
1421
|
+
regular_key = "regular-key-123"
|
1422
|
+
partition_key = "partition-key-456"
|
1423
|
+
|
1424
|
+
# Message with both keys
|
1425
|
+
handle1 = producer.produce(
|
1426
|
+
topic: "partitioner_test_topic",
|
1427
|
+
payload: "test payload 1",
|
1428
|
+
key: regular_key,
|
1429
|
+
partition_key: partition_key
|
1430
|
+
)
|
1431
|
+
|
1432
|
+
# Message with only partition key (should go to same partition)
|
1433
|
+
handle2 = producer.produce(
|
1434
|
+
topic: "partitioner_test_topic",
|
1435
|
+
payload: "test payload 2",
|
1436
|
+
partition_key: partition_key
|
1437
|
+
)
|
1438
|
+
|
1439
|
+
# Message with only regular key (should go to different partition)
|
1440
|
+
handle3 = producer.produce(
|
1441
|
+
topic: "partitioner_test_topic",
|
1442
|
+
payload: "test payload 3",
|
1443
|
+
key: regular_key
|
1444
|
+
)
|
1445
|
+
|
1446
|
+
report1 = handle1.wait(max_wait_timeout: 5)
|
1447
|
+
report2 = handle2.wait(max_wait_timeout: 5)
|
1448
|
+
report3 = handle3.wait(max_wait_timeout: 5)
|
1449
|
+
|
1450
|
+
# Messages 1 and 2 should go to same partition (both use partition_key)
|
1451
|
+
expect(report1.partition).to eq(report2.partition)
|
1452
|
+
|
1453
|
+
# Message 3 should potentially go to different partition (uses regular key)
|
1454
|
+
expect(report3.partition).not_to eq(report1.partition)
|
1455
|
+
end
|
1456
|
+
end
|
1457
|
+
|
1458
|
+
context "edge case combinations with different partitioners" do
|
1459
|
+
it "should handle nil partition key with all partitioners" do
|
1460
|
+
all_partitioners.each do |partitioner|
|
1461
|
+
handle = producer.produce(
|
1462
|
+
topic: "partitioner_test_topic",
|
1463
|
+
payload: "test payload",
|
1464
|
+
key: "test-key",
|
1465
|
+
partition_key: nil,
|
1466
|
+
partitioner: partitioner
|
1467
|
+
)
|
1468
|
+
|
1469
|
+
report = handle.wait(max_wait_timeout: 5)
|
1470
|
+
expect(report.partition).to be >= 0
|
1471
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
|
1475
|
+
it "should handle whitespace-only partition key with all partitioners" do
|
1476
|
+
all_partitioners.each do |partitioner|
|
1477
|
+
handle = producer.produce(
|
1478
|
+
topic: "partitioner_test_topic",
|
1479
|
+
payload: "test payload",
|
1480
|
+
partition_key: " ",
|
1481
|
+
partitioner: partitioner
|
1482
|
+
)
|
1483
|
+
|
1484
|
+
report = handle.wait(max_wait_timeout: 5)
|
1485
|
+
expect(report.partition).to be >= 0
|
1486
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1487
|
+
end
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
it "should handle newline characters in partition key with all partitioners" do
|
1491
|
+
all_partitioners.each do |partitioner|
|
1492
|
+
handle = producer.produce(
|
1493
|
+
topic: "partitioner_test_topic",
|
1494
|
+
payload: "test payload",
|
1495
|
+
partition_key: "key\nwith\nnewlines",
|
1496
|
+
partitioner: partitioner
|
1497
|
+
)
|
1498
|
+
|
1499
|
+
report = handle.wait(max_wait_timeout: 5)
|
1500
|
+
expect(report.partition).to be >= 0
|
1501
|
+
expect(report.partition).to be < producer.partition_count("partitioner_test_topic")
|
1502
|
+
end
|
1503
|
+
end
|
1504
|
+
end
|
1505
|
+
|
1506
|
+
context "debugging partitioner issues" do
|
1507
|
+
it "should show if all partitioners return 0 (indicating a problem)" do
|
1508
|
+
test_key = "debug-test-key"
|
1509
|
+
zero_count = 0
|
1510
|
+
|
1511
|
+
all_partitioners.each do |partitioner|
|
1512
|
+
handle = producer.produce(
|
1513
|
+
topic: "partitioner_test_topic",
|
1514
|
+
payload: "debug payload",
|
1515
|
+
partition_key: test_key,
|
1516
|
+
partitioner: partitioner
|
1517
|
+
)
|
1518
|
+
|
1519
|
+
report = handle.wait(max_wait_timeout: 5)
|
1520
|
+
zero_count += 1 if report.partition == 0
|
1521
|
+
end
|
1522
|
+
|
1523
|
+
expect(zero_count).to be < all_partitioners.size
|
1524
|
+
end
|
1525
|
+
end
|
1526
|
+
end
|
1234
1527
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
Warning[:performance] = true if RUBY_VERSION >= '3.3'
|
4
|
+
Warning[:deprecated] = true
|
5
|
+
$VERBOSE = true
|
6
|
+
|
7
|
+
require 'warning'
|
8
|
+
|
9
|
+
Warning.process do |warning|
|
10
|
+
next unless warning.include?(Dir.pwd)
|
11
|
+
# Allow OpenStruct usage only in specs
|
12
|
+
next if warning.include?('OpenStruct use') && warning.include?('_spec')
|
13
|
+
|
14
|
+
raise "Warning in your code: #{warning}"
|
15
|
+
end
|
16
|
+
|
3
17
|
unless ENV["CI"] == "true"
|
4
18
|
require "simplecov"
|
5
19
|
SimpleCov.start do
|
@@ -14,14 +28,25 @@ require "timeout"
|
|
14
28
|
require "securerandom"
|
15
29
|
|
16
30
|
def rdkafka_base_config
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
31
|
+
if ENV['KAFKA_SSL_ENABLED'] == 'true'
|
32
|
+
{
|
33
|
+
:"bootstrap.servers" => "localhost:9093",
|
34
|
+
# Display statistics and refresh often just to cover those in specs
|
35
|
+
:'statistics.interval.ms' => 1_000,
|
36
|
+
:'topic.metadata.refresh.interval.ms' => 1_000,
|
37
|
+
# SSL Configuration
|
38
|
+
:'security.protocol' => 'SSL',
|
39
|
+
:'ssl.ca.location' => './ssl/ca-cert',
|
40
|
+
:'ssl.endpoint.identification.algorithm' => 'none'
|
41
|
+
}
|
42
|
+
else
|
43
|
+
{
|
44
|
+
:"bootstrap.servers" => "localhost:9092",
|
45
|
+
# Display statistics and refresh often just to cover those in specs
|
46
|
+
:'statistics.interval.ms' => 1_000,
|
47
|
+
:'topic.metadata.refresh.interval.ms' => 1_000
|
48
|
+
}
|
49
|
+
end
|
25
50
|
end
|
26
51
|
|
27
52
|
def rdkafka_config(config_overrides={})
|
@@ -78,18 +103,32 @@ end
|
|
78
103
|
|
79
104
|
def wait_for_message(topic:, delivery_report:, timeout_in_seconds: 30, consumer: nil)
|
80
105
|
new_consumer = consumer.nil?
|
81
|
-
consumer ||= rdkafka_consumer_config.consumer
|
106
|
+
consumer ||= rdkafka_consumer_config('allow.auto.create.topics': true).consumer
|
82
107
|
consumer.subscribe(topic)
|
83
108
|
timeout = Time.now.to_i + timeout_in_seconds
|
109
|
+
retry_count = 0
|
110
|
+
max_retries = 10
|
111
|
+
|
84
112
|
loop do
|
85
113
|
if timeout <= Time.now.to_i
|
86
114
|
raise "Timeout of #{timeout_in_seconds} seconds reached in wait_for_message"
|
87
115
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
116
|
+
|
117
|
+
begin
|
118
|
+
message = consumer.poll(100)
|
119
|
+
if message &&
|
120
|
+
message.partition == delivery_report.partition &&
|
121
|
+
message.offset == delivery_report.offset
|
122
|
+
return message
|
123
|
+
end
|
124
|
+
rescue Rdkafka::RdkafkaError => e
|
125
|
+
if e.code == :unknown_topic_or_part && retry_count < max_retries
|
126
|
+
retry_count += 1
|
127
|
+
sleep(0.1) # Small delay before retry
|
128
|
+
next
|
129
|
+
else
|
130
|
+
raise
|
131
|
+
end
|
93
132
|
end
|
94
133
|
end
|
95
134
|
ensure
|
@@ -110,6 +149,16 @@ def wait_for_unassignment(consumer)
|
|
110
149
|
end
|
111
150
|
end
|
112
151
|
|
152
|
+
def wait_for_topic(admin, topic)
|
153
|
+
admin.metadata(topic)
|
154
|
+
rescue Rdkafka::RdkafkaError => e
|
155
|
+
raise unless e.code == :unknown_topic_or_part
|
156
|
+
|
157
|
+
sleep(0.5)
|
158
|
+
|
159
|
+
retry
|
160
|
+
end
|
161
|
+
|
113
162
|
def notify_listener(listener, &block)
|
114
163
|
# 1. subscribe and poll
|
115
164
|
consumer.subscribe("consume_test_topic")
|
@@ -157,9 +206,9 @@ RSpec.configure do |config|
|
|
157
206
|
end
|
158
207
|
|
159
208
|
config.around(:each) do |example|
|
160
|
-
# Timeout specs after
|
209
|
+
# Timeout specs after 1.5 minute. If they take longer
|
161
210
|
# they are probably stuck
|
162
|
-
Timeout::timeout(
|
211
|
+
Timeout::timeout(90) do
|
163
212
|
example.run
|
164
213
|
end
|
165
214
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: karafka-rdkafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.21.0
|
5
5
|
platform: arm64-darwin
|
6
6
|
authors:
|
7
7
|
- Thijs Cadier
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: logger
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,33 +67,33 @@ dependencies:
|
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '2.6'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - "
|
73
|
+
- - ">"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '12'
|
62
76
|
type: :runtime
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - "
|
80
|
+
- - ">"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '12'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: ostruct
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- - "
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
76
|
-
type: :
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- - "
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: pry
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +150,20 @@ dependencies:
|
|
136
150
|
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: warning
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
139
167
|
description: Modern Kafka client library for Ruby based on librdkafka
|
140
168
|
email:
|
141
169
|
- contact@karafka.io
|
@@ -145,13 +173,21 @@ extra_rdoc_files: []
|
|
145
173
|
files:
|
146
174
|
- ".github/CODEOWNERS"
|
147
175
|
- ".github/FUNDING.yml"
|
148
|
-
- ".github/workflows/
|
149
|
-
- ".github/workflows/
|
176
|
+
- ".github/workflows/ci_linux_alpine_x86_64_musl.yml"
|
177
|
+
- ".github/workflows/ci_linux_alpine_x86_64_musl_complementary.yml"
|
178
|
+
- ".github/workflows/ci_linux_debian_x86_64_gnu.yml"
|
179
|
+
- ".github/workflows/ci_linux_debian_x86_64_gnu_complementary.yml"
|
180
|
+
- ".github/workflows/ci_linux_ubuntu_aarch64_gnu.yml"
|
181
|
+
- ".github/workflows/ci_linux_ubuntu_aarch64_gnu_complementary.yml"
|
182
|
+
- ".github/workflows/ci_linux_ubuntu_x86_64_gnu.yml"
|
183
|
+
- ".github/workflows/ci_linux_ubuntu_x86_64_gnu_complementary.yml"
|
150
184
|
- ".github/workflows/ci_macos_arm64.yml"
|
185
|
+
- ".github/workflows/push_linux_aarch64_gnu.yml"
|
151
186
|
- ".github/workflows/push_linux_x86_64_gnu.yml"
|
152
187
|
- ".github/workflows/push_linux_x86_64_musl.yml"
|
153
188
|
- ".github/workflows/push_macos_arm64.yml"
|
154
189
|
- ".github/workflows/push_ruby.yml"
|
190
|
+
- ".github/workflows/trigger-wiki-refresh.yml"
|
155
191
|
- ".github/workflows/verify-action-pins.yml"
|
156
192
|
- ".gitignore"
|
157
193
|
- ".rspec"
|
@@ -163,13 +199,21 @@ files:
|
|
163
199
|
- MIT-LICENSE
|
164
200
|
- README.md
|
165
201
|
- Rakefile
|
202
|
+
- dist/cyrus-sasl-2.1.28.tar.gz
|
203
|
+
- dist/krb5-1.21.3.tar.gz
|
204
|
+
- dist/openssl-3.0.16.tar.gz
|
205
|
+
- dist/zlib-1.3.1.tar.gz
|
206
|
+
- dist/zstd-1.5.7.tar.gz
|
207
|
+
- docker-compose-ssl.yml
|
166
208
|
- docker-compose.yml
|
167
209
|
- ext/README.md
|
168
210
|
- ext/Rakefile
|
169
211
|
- ext/build_common.sh
|
212
|
+
- ext/build_linux_aarch64_gnu.sh
|
170
213
|
- ext/build_linux_x86_64_gnu.sh
|
171
214
|
- ext/build_linux_x86_64_musl.sh
|
172
215
|
- ext/build_macos_arm64.sh
|
216
|
+
- ext/generate-ssl-certs.sh
|
173
217
|
- ext/librdkafka.dylib
|
174
218
|
- karafka-rdkafka.gemspec
|
175
219
|
- lib/rdkafka.rb
|
@@ -215,34 +259,34 @@ files:
|
|
215
259
|
- lib/rdkafka/producer/partitions_count_cache.rb
|
216
260
|
- lib/rdkafka/version.rb
|
217
261
|
- renovate.json
|
218
|
-
- spec/
|
219
|
-
- spec/rdkafka/
|
220
|
-
- spec/rdkafka/admin/
|
221
|
-
- spec/rdkafka/admin/
|
222
|
-
- spec/rdkafka/admin/
|
223
|
-
- spec/rdkafka/admin/
|
224
|
-
- spec/rdkafka/admin/
|
225
|
-
- spec/rdkafka/admin/
|
226
|
-
- spec/rdkafka/admin/
|
227
|
-
- spec/rdkafka/admin/
|
228
|
-
- spec/rdkafka/admin/
|
229
|
-
- spec/rdkafka/
|
230
|
-
- spec/rdkafka/
|
231
|
-
- spec/rdkafka/
|
232
|
-
- spec/rdkafka/
|
233
|
-
- spec/rdkafka/
|
234
|
-
- spec/rdkafka/consumer/
|
235
|
-
- spec/rdkafka/consumer/
|
236
|
-
- spec/rdkafka/consumer/
|
237
|
-
- spec/rdkafka/
|
238
|
-
- spec/rdkafka/
|
239
|
-
- spec/rdkafka/
|
240
|
-
- spec/rdkafka/
|
241
|
-
- spec/rdkafka/
|
242
|
-
- spec/rdkafka/producer/
|
243
|
-
- spec/rdkafka/producer/
|
244
|
-
- spec/rdkafka/producer/
|
245
|
-
- spec/rdkafka/producer_spec.rb
|
262
|
+
- spec/integrations/ssl_stress_spec.rb
|
263
|
+
- spec/lib/rdkafka/abstract_handle_spec.rb
|
264
|
+
- spec/lib/rdkafka/admin/create_acl_handle_spec.rb
|
265
|
+
- spec/lib/rdkafka/admin/create_acl_report_spec.rb
|
266
|
+
- spec/lib/rdkafka/admin/create_topic_handle_spec.rb
|
267
|
+
- spec/lib/rdkafka/admin/create_topic_report_spec.rb
|
268
|
+
- spec/lib/rdkafka/admin/delete_acl_handle_spec.rb
|
269
|
+
- spec/lib/rdkafka/admin/delete_acl_report_spec.rb
|
270
|
+
- spec/lib/rdkafka/admin/delete_topic_handle_spec.rb
|
271
|
+
- spec/lib/rdkafka/admin/delete_topic_report_spec.rb
|
272
|
+
- spec/lib/rdkafka/admin/describe_acl_handle_spec.rb
|
273
|
+
- spec/lib/rdkafka/admin/describe_acl_report_spec.rb
|
274
|
+
- spec/lib/rdkafka/admin_spec.rb
|
275
|
+
- spec/lib/rdkafka/bindings_spec.rb
|
276
|
+
- spec/lib/rdkafka/callbacks_spec.rb
|
277
|
+
- spec/lib/rdkafka/config_spec.rb
|
278
|
+
- spec/lib/rdkafka/consumer/headers_spec.rb
|
279
|
+
- spec/lib/rdkafka/consumer/message_spec.rb
|
280
|
+
- spec/lib/rdkafka/consumer/partition_spec.rb
|
281
|
+
- spec/lib/rdkafka/consumer/topic_partition_list_spec.rb
|
282
|
+
- spec/lib/rdkafka/consumer_spec.rb
|
283
|
+
- spec/lib/rdkafka/error_spec.rb
|
284
|
+
- spec/lib/rdkafka/metadata_spec.rb
|
285
|
+
- spec/lib/rdkafka/native_kafka_spec.rb
|
286
|
+
- spec/lib/rdkafka/producer/delivery_handle_spec.rb
|
287
|
+
- spec/lib/rdkafka/producer/delivery_report_spec.rb
|
288
|
+
- spec/lib/rdkafka/producer/partitions_count_cache_spec.rb
|
289
|
+
- spec/lib/rdkafka/producer_spec.rb
|
246
290
|
- spec/spec_helper.rb
|
247
291
|
licenses:
|
248
292
|
- MIT
|
@@ -268,7 +312,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
312
|
- !ruby/object:Gem::Version
|
269
313
|
version: '0'
|
270
314
|
requirements: []
|
271
|
-
rubygems_version: 3.6.
|
315
|
+
rubygems_version: 3.6.9
|
272
316
|
specification_version: 4
|
273
317
|
summary: The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka.
|
274
318
|
It wraps the production-ready C client using the ffi gem and targets Kafka 1.0+
|