karafka-rdkafka 0.31.0-aarch64-linux-gnu → 0.32.0-aarch64-linux-gnu

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +83 -35
  3. data/README.md +2 -1
  4. data/ext/librdkafka.so +0 -0
  5. data/karafka-rdkafka.gemspec +4 -3
  6. data/lib/rdkafka/admin/acl_binding_result.rb +4 -16
  7. data/lib/rdkafka/admin/alter_consumer_group_offsets_report.rb +2 -2
  8. data/lib/rdkafka/admin/create_acl_report.rb +1 -3
  9. data/lib/rdkafka/admin/create_topic_report.rb +2 -6
  10. data/lib/rdkafka/admin/delete_consumer_group_offsets_report.rb +2 -2
  11. data/lib/rdkafka/admin/delete_groups_report.rb +2 -6
  12. data/lib/rdkafka/admin/delete_topic_report.rb +2 -6
  13. data/lib/rdkafka/admin/describe_cluster_report.rb +3 -0
  14. data/lib/rdkafka/admin/list_consumer_group_offsets_handle.rb +31 -0
  15. data/lib/rdkafka/admin/list_consumer_group_offsets_report.rb +52 -0
  16. data/lib/rdkafka/admin.rb +180 -10
  17. data/lib/rdkafka/bindings/admin/configs.rb +1 -1
  18. data/lib/rdkafka/bindings/admin.rb +14 -0
  19. data/lib/rdkafka/bindings/callbacks.rb +13 -6
  20. data/lib/rdkafka/bindings/configuration.rb +3 -3
  21. data/lib/rdkafka/bindings/consumer.rb +44 -2
  22. data/lib/rdkafka/bindings/errors.rb +1 -1
  23. data/lib/rdkafka/bindings/handle.rb +1 -1
  24. data/lib/rdkafka/bindings.rb +3 -0
  25. data/lib/rdkafka/callbacks/list_consumer_group_offsets_handler.rb +62 -0
  26. data/lib/rdkafka/callbacks.rb +5 -6
  27. data/lib/rdkafka/config.rb +70 -0
  28. data/lib/rdkafka/consumer/allocator.rb +0 -2
  29. data/lib/rdkafka/consumer/topic_partition_list.rb +7 -7
  30. data/lib/rdkafka/consumer.rb +76 -36
  31. data/lib/rdkafka/defaults.rb +6 -4
  32. data/lib/rdkafka/native_kafka.rb +45 -31
  33. data/lib/rdkafka/producer/partitions_count_cache.rb +109 -26
  34. data/lib/rdkafka/producer.rb +141 -71
  35. data/lib/rdkafka/share_consumer.rb +64 -34
  36. data/lib/rdkafka/version.rb +1 -1
  37. data/lib/rdkafka.rb +4 -1
  38. data/package-lock.json +3 -3
  39. data/renovate.json +7 -0
  40. metadata +5 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31a31d86d0d0ee5888adc297e5bfc9338f18b453b4834095fd4159f6562458ad
4
- data.tar.gz: 1da9da2a1268fb3a9256475dd5cb7e8cccaf8dbaaa061436ae4a1174ba1f3f44
3
+ metadata.gz: d1807a66cb860ccf33c53a7afe9759238ab8c8ebe04d4195e482b1f4c2ab525a
4
+ data.tar.gz: f3c36b50aea64fa52f8481fc5e087ce35aa098e3788d7837dbf51140256a9ce2
5
5
  SHA512:
6
- metadata.gz: 70d99fbf5bf5d225f51b461266c8aac8a4f21e7d5ea860ffd17aa94429ec44bfb52e84e7d770e37b9297218e38147610ecdac24181d93a8c6910c4e791e8a52c
7
- data.tar.gz: 52271992a6802a31a8032264d9a7b61b8f890cdfc479c22402ea9c59c22193f77e5f637318a1701dea71e9c442d03162c1401b3383331d3702b4676f7f978a01
6
+ metadata.gz: 6d429c8e67c82dae33f618dd21f6e9f5b54f17981277c14e0f2e52bbf0ec327df1f8b741e6088da9970d16aaba9aae7547cb1dc9e945013f901645d667c07598
7
+ data.tar.gz: 1408a545d6feb84b61cf5192a5ec3d29ce119df5ea623b083ee27f5eba4bb2fe83344ed5fb4de9e398528079864da30f9335965b63885b07dd55cacaac85978f
data/CHANGELOG.md CHANGED
@@ -1,20 +1,68 @@
1
1
  # Rdkafka Changelog
2
2
 
3
+ ## 0.32.0 (2026-11-04)
4
+ - **[Feature]** Add `Config#consumer_offset_commit_listener`: its `#on_offsets_committed(error, list)` gets the result of every offset commit when the consumer polls or closes, so an async commit that the broker rejects reaches Ruby instead of only a `COMMITFAIL` log line. Ported from rdkafka-ruby (#1061).
5
+ - **[Feature]** Let the offset commit listener define `#on_offsets_commit_failed(error, list)`, called only for failed commits (not on success or `no_offset`). A listener with only this method does not convert the commit offsets of the other commits.
6
+ - **[Feature]** Add `Admin#list_consumer_group_offsets` to read the committed offsets of any consumer group without joining it, with a `require_stable_offsets` option.
7
+ - **[Feature]** Add `validate_only:`, `operation_timeout_ms:` and `request_timeout_ms:` keyword options to `Admin#create_topic` and `#create_partitions`, and the two timeouts to `#delete_topic`. A `create_topic` topic config passed without braces keeps working. Ported from rdkafka-ruby (#1092).
8
+ - [Enhancement] Reduce object shape variations of the admin report classes to one shape per class.
9
+ - [Enhancement] Keep `partition_key` produces working during a cluster outage once the topic partition count is known, instead of raising. Ported from rdkafka-ruby (#1039).
10
+ - [Enhancement] Add `Rdkafka::Config.partition_count_cache_ttl_ms=` to set how long `partition_key` produces reuse a cached partition count (default 30 seconds).
11
+ - [Enhancement] Make `Producer#produce` use about 13% less CPU per call. Ported from rdkafka-ruby (#1064).
12
+ - [Enhancement] Allocate fewer objects per delivered message: delivery callback reports reuse the topic String given to `produce`. Ported from rdkafka-ruby (#1066).
13
+ - [Change] Build the precompiled `x86_64-linux-gnu` and `aarch64-linux-gnu` libraries in an Ubuntu 22.04 container on Ubuntu 24.04 runners, keeping the glibc 2.34 floor after GitHub retires its Ubuntu 22.04 runners. Ported from rdkafka-ruby (#1029).
14
+ - [Change] Depend on `mini_portile2` and `rake` only in the source gem, as only it compiles librdkafka. Apps that got `rake` only through this gem must add it to their Gemfile.
15
+ - [Change] Remove the unused `Rdkafka::Defaults::NATIVE_KAFKA_SYNCHRONIZE_SLEEP_INTERVAL_MS`: `close` and `ShareConsumer#close` now wait for operations in progress without polling. Ported from rdkafka-ruby (#1055).
16
+ - [Maintenance] Fix a use-after-free in the `client_shutdown_dlclose` integration test that made it crash intermittently after its own unmap.
17
+ - [Maintenance] Stabilize the flaky `Consumer#seek` and `#seek_by` "works when a partition is paused" specs on loaded CI runners.
18
+ - [Maintenance] Stop the `client_shutdown_dlclose` integration test from failing with `Errno::ESRCH` when a librdkafka thread exits while its name is read.
19
+ - [Maintenance] Stabilize the flaky `Consumer` "long running consumption" spec, and stop its producer when it fails so its statistics do not break later specs.
20
+ - [Maintenance] Drop `pry` from the development bundle and stop requiring it in the spec helper.
21
+ - [Maintenance] Stabilize the flaky `admin_describe_topics` integration test, which could describe its new topic before the topic was in the broker's metadata.
22
+ - [Maintenance] Name positional String topic parameters `topic_name` (`Consumer#query_watermark_offsets`, `#seek_by`, `Producer#partition_count`, `TopicPartitionList#add_topic` and others). Callers are not affected. Ported from rdkafka-ruby (#1052).
23
+ - [Maintenance] Name the positional String topic parameters of `Producer::PartitionsCountCache` `topic_name`. Callers are not affected.
24
+ - [Maintenance] Cover with integration tests that coordinator errors on group offset requests do not crash the admin client or a consumer without `group.id`. Ported from rdkafka-ruby (#1044).
25
+ - [Maintenance] Skip the bindings signature parity spec on JRuby, whose FFI does not expose function signatures. Ported from rdkafka-ruby (#1046).
26
+ - [Maintenance] Match the FFI pointer expectations in the consumer specs by address, so they pass on JRuby. Ported from rdkafka-ruby (#1047).
27
+ - [Maintenance] Run the `client_shutdown_dlclose` integration test on JRuby on Linux. Ported from rdkafka-ruby (#1049).
28
+ - [Maintenance] Check the native call balance instead of RSS in the leak integration specs on JRuby. Ported from rdkafka-ruby (#1050).
29
+ - [Maintenance] Give the `Consumer#lag` spec a 30 s list offsets wait.
30
+ - [Maintenance] Give the share group offset reset in the `ShareConsumer` specs a 30 s wait and always close its admin, so a timeout no longer fails the stats specs that run after it.
31
+ - [Maintenance] Define `Consumer.finalizer` and `Consumer.report_close_error` in a `class << self` block. Callers are not affected. Ported from rdkafka-ruby (#1068).
32
+ - [Maintenance] Wait 30 s for the `before(:suite)` topic creates. Ported from rdkafka-ruby (#1065).
33
+ - [Maintenance] Run the concurrent first produce checks on JRuby, now that `close` no longer hangs there after concurrent produces. Ported from rdkafka-ruby (#1083).
34
+ - [Maintenance] Create the topics of the producer `timestamp` specs with `retention.ms: -1`, so broker retention no longer deletes their 2017-timestamped messages before the specs read them back. Ported from rdkafka-ruby (#1077).
35
+ - [Maintenance] Time out the SSL spec step of the Ubuntu aarch64 complementary CI workflow after 25 minutes, so a hanging example fails the step and its log is kept. Ported from rdkafka-ruby (#1086).
36
+ - [Maintenance] Fix the YARD notes of `events_poll_nb_each` and `Consumer#poll_nb_each`: they do not hold a lock while they loop, so other operations run concurrently and only `close` waits. Ported from rdkafka-ruby (#1089).
37
+ - [Maintenance] Stop the fake SSL servers in integration specs without `Thread#kill`. Ported from rdkafka-ruby (#1059).
38
+ - [Fix] Stop `Consumer#store_offset` and other calls that pass partition metadata from raising `NoMethodError` on JRuby. Ported from rdkafka-ruby (#1045).
39
+ - [Fix] Pass the error buffer size to librdkafka as `size_t` when setting config options and creating clients.
40
+ - [Fix] Raise `Rdkafka::LibraryLoadError` with the glibc upgrade hint instead of `NameError` when the precompiled librdkafka needs a newer glibc. Ported from rdkafka-ruby (#1031).
41
+ - [Fix] Report a failed consumer close (e.g. of a fatally-errored consumer) to `Rdkafka::Config.error_callback` instead of dropping it. `Consumer#close` still does not raise.
42
+ - [Fix] Stop the statistics, error and OAuth token refresh callbacks from raising `NoMethodError` when another thread clears the global callback while they run. On JRuby this aborted the process from the polling thread. Ported from rdkafka-ruby (#1058).
43
+ - [Fix] Stop `ShareConsumer#close` from hanging forever when it runs while the first partition assignment waits for topic metadata, by patching the bundled librdkafka (confluentinc/librdkafka#5658).
44
+ - [Fix] Pass the `#oauthbearer_set_token` size arguments to librdkafka as `size_t`, so the token set error is no longer truncated at random on JRuby.
45
+ - [Fix] Pass the fatal error buffer size (used by `Producer#fatal_error` and the error callback) and the config resource array count to librdkafka as `size_t`.
46
+ - [Fix] Stop the producer from retrying a message without backoff after about 25 retries, by patching the bundled librdkafka (confluentinc/librdkafka#5646).
47
+ - [Fix] Stop the rebalance callback from raising `LocalJumpError` when called for a client whose opaque is already gone.
48
+ - [Fix] Create one topic handle per topic when many threads produce to a new topic at once. On JRuby this race leaked topic handles and could crash with a segfault; `produce` now raises `TopicHandleCreationError` instead of passing a missing handle to librdkafka. Ported from rdkafka-ruby (#1056).
49
+ - [Fix] Count a client's (and a share consumer's) operations in progress under one lock, so on JRuby `close` no longer hangs or destroys the client while another thread still uses it. Ported from rdkafka-ruby (#1055).
50
+
3
51
  ## 0.31.0 (2026-10-12)
52
+ - **[EOL]** Drop Ruby 3.2 support; require Ruby 3.3+.
4
53
  - [Feature] Add `Admin#describe_cluster` to get the cluster id, controller and broker nodes (with racks) without a full metadata request. Ported from rdkafka-ruby (#1015).
5
- - [Feature] Add `Admin#describe_topics` to get topic ids, partition leaders and replicas, and per-topic errors. Both methods can also return the operations the client is authorized to perform. Ported from rdkafka-ruby (#1015).
6
- - [Feature] Add `Admin#describe_consumer_groups` to read the state, type, coordinator, authorized operations and members (with their current and target partition assignments) of consumer groups. Ported from rdkafka-ruby (#1016).
54
+ - [Feature] Add `Admin#describe_topics` to get topic ids, partition leaders, replicas and per-topic errors. Both methods can also return the client's authorized operations. Ported from rdkafka-ruby (#1015).
55
+ - [Feature] Add `Admin#describe_consumer_groups` to read consumer groups' state, type, coordinator, authorized operations and members with their current and target assignments. Ported from rdkafka-ruby (#1016).
7
56
  - [Feature] Add `status`, `latency` and `broker_id` to `Producer::DeliveryReport`, with `#persisted?`, `#possibly_persisted?` and `#not_persisted?`, so a failed delivery tells whether a retry may duplicate the message. Ported from rdkafka-ruby (#1019).
8
57
  - [Enhancement] Bump librdkafka to `2.16.0` for OpenSSL and libcurl security fixes. Admin requests in flight on a decommissioned broker now fail with a retryable transport error. Ported from rdkafka-ruby (#1020).
9
58
  - [Enhancement] Bump the bundled OpenSSL to `3.5.9` (LTS) for its security fixes. Ported from rdkafka-ruby (#1007).
10
59
  - [Enhancement] Read each pointer field once in `Message#initialize`, saving 3 allocations per consumed message. Ported from rdkafka-ruby (#1026).
11
- - [Change] Drop Ruby 3.2 support; require Ruby 3.3+.
12
60
  - [Change] Build the precompiled `aarch64-linux-musl` gem on Alpine `3.24` (was `3.23`), matching `x86_64-linux-musl`. Ported from rdkafka-ruby (#1012).
13
61
  - [Change] Build the precompiled `macos_arm64` library on macOS 26 with the minimum macOS pinned to 14.0, instead of inheriting it from the build host. Ported from rdkafka-ruby (#1013).
14
62
  - [Maintenance] Split `lib/rdkafka/bindings.rb` into per-area files under `lib/rdkafka/bindings/`. `Rdkafka::Bindings` is unchanged. Ported from rdkafka-ruby (#1022).
15
- - [Maintenance] Stabilize the flaky partitions count cache "multiple topics with different TTLs" spec by driving its clock instead of sleeping. Ported from rdkafka-ruby (#1028).
63
+ - [Maintenance] Stabilize a flaky partitions count cache spec. Ported from rdkafka-ruby (#1028).
16
64
  - [Fix] Sort merged share-group async acknowledgements so the broker does not reject them with `invalid_request` (librdkafka patch).
17
- - [Fix] Release share records acquired by an in-flight fetch on unsubscribe instead of keeping them locked (librdkafka patch). `ShareConsumer#unsubscribe` now closes the share sessions like `#close` does and waits for that (up to `fetch.wait.max.ms` with a fetch in flight).
65
+ - [Fix] Release share records acquired by an in-flight fetch on unsubscribe instead of keeping them locked (librdkafka patch). `ShareConsumer#unsubscribe` now closes the share sessions like `#close` and can wait up to `fetch.wait.max.ms`.
18
66
 
19
67
  ## 0.30.2 (2026-10-01)
20
68
  - [Feature] Add `ShareConsumer#events_poll` (and `#events_poll_nb`) to service the statistics, error, log and OAuthBearer callbacks without acquiring records.
@@ -23,59 +71,59 @@
23
71
  - [Fix] Set `ShareConsumer#name` from the native handle at creation, so name-based callback routing (e.g. Karafka) no longer drops share-consumer statistics and errors.
24
72
 
25
73
  ## 0.30.0 (2026-09-25)
26
- - [Fix] Register share consumers in `Rdkafka::Clients` and destroy the native handle when `Config#share_consumer` fails part-way, so a share consumer is no longer missed by the `at_exit` shutdown hook.
27
74
  - [Feature] Add preview support for KIP-932 share groups ("Queues for Kafka") via `Rdkafka::ShareConsumer` (`Config#share_consumer`), with per-record acknowledgements (`:accept`, `:release`, `:reject`). Requires Apache Kafka 4.2.0+ with share groups enabled. Not production-ready.
28
- - [Enhancement] `RdkafkaError.build_from_c` now uses the human-readable string librdkafka attaches to the `rd_kafka_error_t` instead of `rd_kafka_err2str`, improving diagnostics for every error-pointer path.
29
- - [Enhancement] Refactor the `Helpers::OAuth` token plumbing around two private hooks so the share consumer overrides only those instead of duplicating both public methods.
30
- - [Fix] Make `ShareConsumer#close` thread-safe: it now waits for in-flight operations (mirroring `NativeKafka`), preventing a double destroy when two threads race `close`.
31
- - [Fix] Keep the `ShareConsumer` native handle and its GC finalizer when `close`/`destroy` report an error, so the client is no longer leaked and `close` stays retriable.
32
- - [Fix] Pin the acknowledgement commit callback `FFI::Function` for the lifetime of the `ShareConsumer`, preventing a use-after-free when an unclosed consumer is garbage collected.
33
- - [Fix] Make `ShareConsumer` fork-aware (mirroring `NativeKafka`): it reports `closed?` in a forked child, which no longer segfaults on `close` or finalization.
34
- - [Fix] Rescue `ClosedConsumerError` in `ShareConsumer#each` only around `poll`, so a `ClosedConsumerError` raised inside the block propagates instead of silently ending iteration. Like `#poll`, `#each` can also yield an `RdkafkaError` for a record that fails to build.
35
- - [Fix] Raise `ArgumentError` for `ShareConsumer#subscribe` without topics, which librdkafka otherwise treats as an unsubscribe without error, silently dropping the subscription.
36
- - [Fix] Capture the librdkafka client name onto `ShareConsumer#name` from the OAuthBearer token refresh callback, since the share handle has no native name accessor for the documented name-based oauth callback routing.
37
- - [Fix] Update `ext/build_common.sh` (precompiled builds) to librdkafka `2.15.0` and its tarball checksum; it still pinned `2.14.1`, whose tarball is no longer vendored.
38
- - [Fix] Stop the `share_consumer_multi_member` integration spec from failing on an at-least-once redelivery; it now tracks distinct payloads and fails only when a record is never delivered.
39
- - [Fix] Apply the same at-least-once tolerance to the `share_consumer_explicit_ack` integration spec: require only the released record to be redelivered, forbid the rejected one, and tolerate an accepted record reappearing.
40
- - [Fix] Add the `nofile` ulimit to `docker-compose-ssl.yml` (mirroring `docker-compose.yml`) so the SSL CI broker does not exhaust file descriptors under the topic-heavy share-consumer suite.
41
- - [Fix] Enable KIP-932 share groups on the macOS CI broker, whose KRaft config never opted into the share rebalance protocol, so its share-consumer spec no longer receives zero records. `CONFLUENT_VERSION` is bumped to `8.3.0`.
42
- - [Enhancement] Add `share_consumer_implicit_ack` and `share_consumer_multi_topic` integration specs.
43
- - [Fix] Stop the `statistics_unassigned_producer` integration spec from flaking on a metadata-propagation race by retrying the produce on `unknown_topic_or_part` and `leader_not_available`.
44
- - [Fix] Also stabilize the `statistics_unassigned_producer` integration spec against a delivery wait that outlives its budget: it now uses the default 60s handle wait and retries on `WaitTimeoutError`.
45
- - [Fix] Stabilize the `consumer_memberid_clusterid_leak` integration spec against RSS measurement noise on Ruby 4.0 by compacting the heap before sampling and raising the ceiling to 3 MB.
46
- - [Note] Share consumers emit the regular consumer statistics through `statistics_callback`. librdkafka 2.15.0 has no share-specific metrics, so the `topics` section has no partition entries.
47
75
  - [Feature] Add `Admin#alter_consumer_group_offsets` and `Admin#delete_consumer_group_offsets` to set or clear a consumer group's committed offsets from the admin client. Ported from rdkafka-ruby (#983).
76
+ - [Enhancement] Use the error string librdkafka attaches to each error in `RdkafkaError.build_from_c`, for clearer error messages.
77
+ - [Enhancement] Refactor the `Helpers::OAuth` token handling so the share consumer reuses it instead of duplicating it.
48
78
  - [Enhancement] Bump librdkafka to `2.15.1` for OpenSSL and libcurl security fixes. It changes how IPv6 addresses are formatted and validated against broker certificates.
49
79
  - [Enhancement] Bump the bundled zlib to `1.3.2`.
50
80
  - [Enhancement] Bump the bundled MIT Kerberos (krb5) to `1.22.2`. Ported from rdkafka-ruby (#979).
51
81
  - [Enhancement] Add `Rdkafka::Config.partitioner_key_uses_bytesize` to hash partition keys by byte length, matching other Kafka clients for multibyte keys. Defaults to `false`. Ported from rdkafka-ruby (#985).
82
+ - [Maintenance] Stop the `share_consumer_multi_member` integration spec from failing on an at-least-once redelivery.
83
+ - [Maintenance] Apply the same at-least-once tolerance to the `share_consumer_explicit_ack` integration spec.
84
+ - [Maintenance] Add the `nofile` ulimit to the SSL CI broker so the share-consumer suite does not exhaust file descriptors.
85
+ - [Maintenance] Enable KIP-932 share groups on the macOS CI broker and bump its `CONFLUENT_VERSION` to `8.3.0`.
86
+ - [Maintenance] Add `share_consumer_implicit_ack` and `share_consumer_multi_topic` integration specs.
87
+ - [Maintenance] Stop the `statistics_unassigned_producer` integration spec from flaking on a metadata-propagation race.
88
+ - [Maintenance] Also stabilize the `statistics_unassigned_producer` integration spec against delivery wait timeouts.
89
+ - [Maintenance] Stabilize the `consumer_memberid_clusterid_leak` integration spec against RSS measurement noise on Ruby 4.0.
52
90
  - [Maintenance] Derive the zlib `CHECKSUMS` entry from `ZLIB_VERSION`.
53
91
  - [Maintenance] Drop the unused `dist/openssl-3.0.16.tar.gz` build cache.
54
- - [Fix] Honor the `isolation_level:` argument to `Admin#list_offsets`, which was silently ignored. Ported from rdkafka-ruby (#983).
55
- - [Fix] Return correct results for every item of a multi-item topic, partition, group or ACL admin request, not just the first. Ported from rdkafka-ruby (#987).
56
92
  - [Maintenance] Fix a use-after-free in the multi-item admin integration test that made it flaky on newer glibc. Ported from rdkafka-ruby (#991).
57
93
  - [Maintenance] Stabilize consumer specs on slow CI runners. The assignment wait is tunable via `RDKAFKA_TEST_ASSIGNMENT_TIMEOUT`. Ported from rdkafka-ruby (#990).
94
+ - [Fix] Register share consumers in `Rdkafka::Clients` and destroy the native handle when `Config#share_consumer` fails part-way, so a share consumer is no longer missed by the `at_exit` shutdown hook.
95
+ - [Fix] Make `ShareConsumer#close` thread-safe: it now waits for in-flight operations (mirroring `NativeKafka`), preventing a double destroy when two threads race `close`.
96
+ - [Fix] Keep the `ShareConsumer` native handle and its GC finalizer when `close`/`destroy` report an error, so the client is no longer leaked and `close` stays retriable.
97
+ - [Fix] Prevent a use-after-free when an unclosed `ShareConsumer` is garbage collected.
98
+ - [Fix] Make `ShareConsumer` fork-aware (mirroring `NativeKafka`): it reports `closed?` in a forked child, which no longer segfaults on `close` or finalization.
99
+ - [Fix] Rescue `ClosedConsumerError` in `ShareConsumer#each` only around `poll`, so a `ClosedConsumerError` raised inside the block propagates instead of silently ending iteration. Like `#poll`, `#each` can also yield an `RdkafkaError` for a record that fails to build.
100
+ - [Fix] Raise `ArgumentError` for `ShareConsumer#subscribe` without topics, which librdkafka otherwise treats as an unsubscribe without error, silently dropping the subscription.
101
+ - [Fix] Set `ShareConsumer#name` from the OAuthBearer token refresh callback, so name-based OAuth callback routing works for share consumers.
102
+ - [Fix] Update `ext/build_common.sh` (precompiled builds) to librdkafka `2.15.0` and its tarball checksum; it still pinned `2.14.1`, whose tarball is no longer vendored.
103
+ - [Fix] Honor the `isolation_level:` argument to `Admin#list_offsets`, which was silently ignored. Ported from rdkafka-ruby (#983).
104
+ - [Fix] Return correct results for every item of a multi-item topic, partition, group or ACL admin request, not just the first. Ported from rdkafka-ruby (#987).
105
+ - [Note] Share consumers emit the regular consumer statistics through `statistics_callback`. librdkafka 2.15.0 has no share-specific metrics, so the `topics` section has no partition entries.
58
106
 
59
107
  ## 0.29.0 (2026-09-14)
60
108
  - [Enhancement] Bump librdkafka to `2.15.0` (staying on `2.15.0` rather than `2.15.1` so users hitting a regression in `2.15.1` have a stable fallback).
61
109
 
62
- ## 0.28.2 (2026-09-11)
110
+ ## 0.28.2 (2026-09-12)
111
+ - [Maintenance] Bump the bundled OpenSSL used by the precompiled builds to `3.5.8` (LTS). Ported from rdkafka-ruby (#972, Scott Francis).
63
112
  - [Fix] Close live clients before Ruby shutdown finalization, preventing a possible segfault on exit. Ported from rdkafka-ruby (#964, Alex Selesse).
64
113
  - [Fix] Destroy the native handle when client construction fails partway, so it is no longer orphaned. Ported from rdkafka-ruby (#964, Alex Selesse).
65
114
  - [Fix] Fix a double-free in `Consumer#poll_batch`/`#poll_batch_nb` that could abort the process when building a message raised a non-`RdkafkaError`. Ported from rdkafka-ruby (#973).
66
115
  - [Fix] Free native resources when `Admin#describe_configs`/`#incremental_alter_configs` raise while building their request (e.g. a non-String resource name). Ported from rdkafka-ruby (#973).
67
116
  - [Fix] Raise `ConfigError` instead of segfaulting when `Admin#describe_configs`/`#incremental_alter_configs` get an empty resource name or a negative resource type. Ported from rdkafka-ruby (#973).
68
117
  - [Fix] Stop the topic-partition metadata string from being freed while librdkafka still uses it. Ported from rdkafka-ruby (#969, Randy Stauner).
69
- - [Maintenance] Bump the bundled OpenSSL used by the precompiled builds to `3.5.8` (LTS). Ported from rdkafka-ruby (#972, Scott Francis).
70
118
 
71
- ## v0.28.1 (2026-09-04)
119
+ ## 0.28.1 (2026-09-04)
72
120
  - [Enhancement] Add `Admin#delete_records` to delete messages in a partition up to a given offset, or all current data with `:end`. Ported from rdkafka-ruby (#956).
73
121
  - [Enhancement] Add `Admin#list_consumer_groups` for a cluster-wide listing of consumer groups. Ported from rdkafka-ruby (#955).
74
122
  - [Fix] Make `NativeKafka#close` fork-aware so a forked child no longer segfaults on exit. Handles record their creator pid and skip the native teardown in any other process.
75
123
  - [Fix] Stabilize the flaky partitions count cache statistics spec.
76
124
  - [Fix] Stabilize the `to_native_tpl` leak integration spec against RSS measurement noise.
77
125
 
78
- ## v0.28.0 (2026-07-12)
126
+ ## 0.28.0 (2026-07-12)
79
127
  - [Enhancement] Bump librdkafka to `2.14.2` (maintenance release with bundled dependency CVE fixes and a fix for duplicate groups in `ListConsumerGroups`).
80
128
  - [Enhancement] Add `Consumer#metadata` and `Producer#metadata`, mirroring `Admin#metadata`, to fetch cluster metadata without a separate admin connection.
81
129
  - [Enhancement] Name the failing topic and partition in `RdkafkaError`s raised for per-partition `list_offsets` errors.
@@ -111,10 +159,10 @@
111
159
  ## 0.27.2 (2026-05-21)
112
160
  - [Enhancement] `poll_batch` and `poll_batch_nb` now return error events inline as `RdkafkaError` objects rather than raising on the first error. The return type is `Array<Message, RdkafkaError>` and callers are responsible for handling errors in the result.
113
161
 
114
- ## 0.27.1 (2026-05-14)
162
+ ## 0.27.1 (2026-05-15)
115
163
  - [Fix] `poll_nb`, `poll_nb_each`, `poll_batch` and `poll_batch_nb` now raise `RdkafkaError` with `details` populated (`{topic:, partition:, offset:}`) when a message contains an error, consistent with `poll`.
116
164
 
117
- ## 0.27.0 (2026-05-08)
165
+ ## 0.27.0 (2026-05-10)
118
166
  - [Feature] Add `Consumer#poll_batch(timeout_ms, max_items:)` and `Consumer#poll_batch_nb(timeout_ms, max_items:)` for batch message polling via `rd_kafka_consume_batch_queue` (from upstream).
119
167
  - [Enhancement] Bump librdkafka to `2.14.1`.
120
168
  - [Fix] Fix resource leak in `Admin#describe_configs` and `Admin#incremental_alter_configs` where `admin_options_ptr` and `queue_ptr` were not destroyed in the ensure block (from upstream).
@@ -179,7 +227,7 @@
179
227
  - [Enhancement] Force lock FFI to 1.17.1 or higher to include critical bug fixes around GCC, write barriers, and thread restarts for forks.
180
228
  - [Fix] Fix for Core dump when providing extensions to oauthbearer_set_token (dssjoblom)
181
229
 
182
- ## 0.22.2 (2025-10-09)
230
+ ## 0.22.2 (2025-10-10)
183
231
  - [Fix] Fix Github Action Ruby reference preventing non-compiled releases.
184
232
 
185
233
  ## 0.22.1 (2025-10-09)
@@ -201,7 +249,7 @@
201
249
  - [Enhancement] Introduce an integration suite layer for non RSpec specs execution.
202
250
  - [Fix] Add `json` gem as a dependency (was missing but used).
203
251
 
204
- ## 0.20.1 (2025-07-17)
252
+ ## 0.20.1 (2025-07-18)
205
253
  - [Enhancement] Drastically increase number of platforms in the integration suite
206
254
  - [Fix] Support Ubuntu `22.04` and older Alpine precompiled versions
207
255
  - [Fix] FFI::DynamicLibrary.load_library': Could not open library
data/README.md CHANGED
@@ -63,11 +63,12 @@ Contributions should generally be made to the upstream [rdkafka-ruby repository]
63
63
 
64
64
  | karafka-rdkafka | librdkafka | patches |
65
65
  |-|-|-|
66
+ | 0.32.x (2026-11-04) | 2.16.0 (2026-10-06) | yes |
66
67
  | 0.31.x (2026-10-12) | 2.16.0 (2026-10-06) | yes |
67
68
  | 0.30.x (2026-09-25) | 2.15.1 (2026-09-09) | yes |
68
69
  | 0.29.x (2026-09-14) | 2.15.0 (2026-06-30) | yes |
69
70
  | 0.28.x (2026-07-12) | 2.14.2 (2026-06-03) | yes |
70
- | 0.27.x (2026-05-08) | 2.14.1 (2026-04-15) | yes |
71
+ | 0.27.x (2026-05-10) | 2.14.1 (2026-04-15) | yes |
71
72
  | 0.26.x (2026-04-11) | 2.14.0 (2026-04-01) | yes |
72
73
  | 0.25.x (2026-04-02) | 2.13.2 (2026-03-02) | yes |
73
74
  | 0.24.x (2026-02-25) | 2.13.0 (2026-01-05) | yes |
data/ext/librdkafka.so CHANGED
Binary file
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
6
6
  gem.authors = ["Thijs Cadier", "Maciej Mensfeld"]
7
7
  gem.email = ["contact@karafka.io"]
8
8
  gem.description = "Modern Kafka client library for Ruby based on librdkafka"
9
- gem.summary = "The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka. It wraps the production-ready C client using the ffi gem and targets Kafka 1.0+ and Ruby 2.7+."
9
+ gem.summary = "The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka. It wraps the production-ready C client using the ffi gem and targets Kafka 1.0+ and Ruby 3.3+."
10
10
  gem.license = "MIT"
11
11
 
12
12
  gem.name = "karafka-rdkafka"
@@ -65,13 +65,14 @@ Gem::Specification.new do |gem|
65
65
  end
66
66
 
67
67
  gem.extensions = %w[ext/Rakefile]
68
+
69
+ gem.add_dependency "mini_portile2", "~> 2.6"
70
+ gem.add_dependency "rake", "> 12"
68
71
  end
69
72
 
70
73
  gem.add_dependency "ffi", "~> 1.17.1"
71
74
  gem.add_dependency "json", "> 2.0"
72
75
  gem.add_dependency "logger"
73
- gem.add_dependency "mini_portile2", "~> 2.6"
74
- gem.add_dependency "rake", "> 12"
75
76
 
76
77
  gem.metadata = {
77
78
  "funding_uri" => "https://karafka.io/#become-pro",
@@ -18,30 +18,18 @@ module Rdkafka
18
18
  rd_kafka_error_pointer = Rdkafka::Bindings.rd_kafka_AclBinding_error(matching_acl)
19
19
  @result_error = Rdkafka::Bindings.rd_kafka_error_code(rd_kafka_error_pointer)
20
20
  error_string = Rdkafka::Bindings.rd_kafka_error_string(rd_kafka_error_pointer)
21
-
22
- if error_string != FFI::Pointer::NULL
23
- @error_string = error_string.read_string
24
- end
21
+ @error_string = error_string.null? ? nil : error_string.read_string
25
22
 
26
23
  @matching_acl_resource_type = Rdkafka::Bindings.rd_kafka_AclBinding_restype(matching_acl)
27
24
  matching_acl_resource_name = Rdkafka::Bindings.rd_kafka_AclBinding_name(matching_acl)
28
-
29
- if matching_acl_resource_name != FFI::Pointer::NULL
30
- @matching_acl_resource_name = matching_acl_resource_name.read_string
31
- end
25
+ @matching_acl_resource_name = matching_acl_resource_name.null? ? nil : matching_acl_resource_name.read_string
32
26
 
33
27
  @matching_acl_resource_pattern_type = Rdkafka::Bindings.rd_kafka_AclBinding_resource_pattern_type(matching_acl)
34
28
  matching_acl_principal = Rdkafka::Bindings.rd_kafka_AclBinding_principal(matching_acl)
35
-
36
- if matching_acl_principal != FFI::Pointer::NULL
37
- @matching_acl_principal = matching_acl_principal.read_string
38
- end
29
+ @matching_acl_principal = matching_acl_principal.null? ? nil : matching_acl_principal.read_string
39
30
 
40
31
  matching_acl_host = Rdkafka::Bindings.rd_kafka_AclBinding_host(matching_acl)
41
-
42
- if matching_acl_host != FFI::Pointer::NULL
43
- @matching_acl_host = matching_acl_host.read_string
44
- end
32
+ @matching_acl_host = matching_acl_host.null? ? nil : matching_acl_host.read_string
45
33
 
46
34
  @matching_acl_operation = Rdkafka::Bindings.rd_kafka_AclBinding_operation(matching_acl)
47
35
  @matching_acl_permission_type = Rdkafka::Bindings.rd_kafka_AclBinding_permission_type(matching_acl)
@@ -20,8 +20,8 @@ module Rdkafka
20
20
  # @param result_name [FFI::Pointer] pointer to the group name
21
21
  # @param partitions_ptr [FFI::Pointer] pointer to the per partition result list
22
22
  def initialize(error_string, result_name, partitions_ptr = FFI::Pointer::NULL)
23
- @error_string = error_string.read_string if error_string != FFI::Pointer::NULL
24
- @group_name = result_name.read_string if result_name != FFI::Pointer::NULL
23
+ @error_string = error_string.null? ? nil : error_string.read_string
24
+ @group_name = result_name.null? ? nil : result_name.read_string
25
25
  @partitions = extract_partitions(partitions_ptr)
26
26
  end
27
27
 
@@ -17,9 +17,7 @@ module Rdkafka
17
17
  # @param rdkafka_response_string [FFI::Pointer] pointer to response string
18
18
  def initialize(rdkafka_response:, rdkafka_response_string:)
19
19
  @rdkafka_response = rdkafka_response
20
- if rdkafka_response_string != FFI::Pointer::NULL
21
- @rdkafka_response_string = rdkafka_response_string.read_string
22
- end
20
+ @rdkafka_response_string = rdkafka_response_string.null? ? nil : rdkafka_response_string.read_string
23
21
  end
24
22
  end
25
23
  end
@@ -15,12 +15,8 @@ module Rdkafka
15
15
  # @param error_string [FFI::Pointer] pointer to error string
16
16
  # @param result_name [FFI::Pointer] pointer to topic name
17
17
  def initialize(error_string, result_name)
18
- if error_string != FFI::Pointer::NULL
19
- @error_string = error_string.read_string
20
- end
21
- if result_name != FFI::Pointer::NULL
22
- @result_name = result_name.read_string
23
- end
18
+ @error_string = error_string.null? ? nil : error_string.read_string
19
+ @result_name = result_name.null? ? nil : result_name.read_string
24
20
  end
25
21
  end
26
22
  end
@@ -20,8 +20,8 @@ module Rdkafka
20
20
  # @param result_name [FFI::Pointer] pointer to the group name
21
21
  # @param partitions_ptr [FFI::Pointer] pointer to the per partition result list
22
22
  def initialize(error_string, result_name, partitions_ptr = FFI::Pointer::NULL)
23
- @error_string = error_string.read_string if error_string != FFI::Pointer::NULL
24
- @group_name = result_name.read_string if result_name != FFI::Pointer::NULL
23
+ @error_string = error_string.null? ? nil : error_string.read_string
24
+ @group_name = result_name.null? ? nil : result_name.read_string
25
25
  @partitions = extract_partitions(partitions_ptr)
26
26
  end
27
27
 
@@ -15,12 +15,8 @@ module Rdkafka
15
15
  # @param error_string [FFI::Pointer] pointer to error string
16
16
  # @param result_name [FFI::Pointer] pointer to group name
17
17
  def initialize(error_string, result_name)
18
- if error_string != FFI::Pointer::NULL
19
- @error_string = error_string.read_string
20
- end
21
- if result_name != FFI::Pointer::NULL
22
- @result_name = result_name.read_string
23
- end
18
+ @error_string = error_string.null? ? nil : error_string.read_string
19
+ @result_name = result_name.null? ? nil : result_name.read_string
24
20
  end
25
21
  end
26
22
  end
@@ -15,12 +15,8 @@ module Rdkafka
15
15
  # @param error_string [FFI::Pointer] pointer to error string
16
16
  # @param result_name [FFI::Pointer] pointer to topic name
17
17
  def initialize(error_string, result_name)
18
- if error_string != FFI::Pointer::NULL
19
- @error_string = error_string.read_string
20
- end
21
- if result_name != FFI::Pointer::NULL
22
- @result_name = result_name.read_string
23
- end
18
+ @error_string = error_string.null? ? nil : error_string.read_string
19
+ @result_name = result_name.null? ? nil : result_name.read_string
24
20
  end
25
21
  end
26
22
  end
@@ -27,6 +27,9 @@ module Rdkafka
27
27
  # @param result_ptr [FFI::Pointer] pointer to the `rd_kafka_DescribeCluster_result_t`
28
28
  def initialize(result_ptr)
29
29
  @nodes = []
30
+ @cluster_id = nil
31
+ @controller = nil
32
+ @authorized_operations = nil
30
33
 
31
34
  return if result_ptr.null?
32
35
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ class Admin
5
+ # Handle for list consumer group offsets operation
6
+ class ListConsumerGroupOffsetsHandle < AbstractHandle
7
+ layout :pending, :bool,
8
+ :response, :int
9
+
10
+ # @return [String] the name of the operation
11
+ def operation_name
12
+ "list consumer group offsets"
13
+ end
14
+
15
+ # Creates the result report
16
+ # @return [ListConsumerGroupOffsetsReport]
17
+ def create_result
18
+ prepared_result
19
+ end
20
+
21
+ # Raises an error if the operation failed
22
+ # @raise [RdkafkaError]
23
+ def raise_error
24
+ raise RdkafkaError.new(
25
+ self[:response],
26
+ broker_message: broker_message
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ class Admin
5
+ # Report for list consumer group offsets operation result
6
+ class ListConsumerGroupOffsetsReport
7
+ # @return [String, nil] the group the operation ran against
8
+ attr_reader :group_name
9
+
10
+ # @return [String, nil] group level error message, if any
11
+ attr_reader :error_string
12
+
13
+ # Committed offsets per partition, each with `:topic`, `:partition`, `:offset` (nil when
14
+ # the group has no committed offset for it or the partition has an `:error`), `:metadata`
15
+ # (nil when none was committed) and `:error` (an `RdkafkaError` or nil).
16
+ # @return [Array<Hash>]
17
+ attr_reader :partitions
18
+
19
+ # @param error_string [FFI::Pointer] pointer to the group level error string
20
+ # @param result_name [FFI::Pointer] pointer to the group name
21
+ # @param partitions_ptr [FFI::Pointer] pointer to the per partition result list
22
+ def initialize(error_string, result_name, partitions_ptr = FFI::Pointer::NULL)
23
+ @error_string = error_string.null? ? nil : error_string.read_string
24
+ @group_name = result_name.null? ? nil : result_name.read_string
25
+ @partitions = extract_partitions(partitions_ptr)
26
+ end
27
+
28
+ private
29
+
30
+ # @param partitions_ptr [FFI::Pointer] pointer to a native topic partition list
31
+ # @return [Array<Hash>]
32
+ def extract_partitions(partitions_ptr)
33
+ return [] if partitions_ptr.nil? || partitions_ptr.null?
34
+
35
+ native = Bindings::TopicPartitionList.new(partitions_ptr)
36
+
37
+ Array.new(native[:cnt]) do |i|
38
+ tp = Bindings::TopicPartition.new(native[:elems] + (i * Bindings::TopicPartition.size))
39
+ offset = tp[:offset]
40
+
41
+ {
42
+ topic: tp[:topic],
43
+ partition: tp[:partition],
44
+ offset: (offset == Bindings::RD_KAFKA_OFFSET_INVALID) ? nil : offset,
45
+ metadata: tp[:metadata].null? ? nil : tp[:metadata].read_string(tp[:metadata_size]),
46
+ error: tp[:err].zero? ? nil : RdkafkaError.new(tp[:err])
47
+ }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end