rdkafka 0.26.0-aarch64-linux-gnu → 0.28.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2c2169a9f9444181c281c137827e6c534ce85c815393237697a3207b4d2c3ec
4
- data.tar.gz: 1fa3ac1e46333c23269edb3d476578969003be8f379553b442fe67e08a076b36
3
+ metadata.gz: a3b989ab756f525201a13a02b0522c4f5c5db3a02e1e673b664e8fb07655a933
4
+ data.tar.gz: 6e998687537fa7b1421038db9ecd9a8e14be3816f7d7778df27e96715247973a
5
5
  SHA512:
6
- metadata.gz: 508c1ccfee398c9e5a124e5430b8c580405f77db7f0967cfb6018ae1730232d4104ccef643a3b3fcf3263e65bd5d6d45a43482a843212e0633439d5c4db9d6c8
7
- data.tar.gz: 3a3e702c3ed614a943807b7737ae837d719225aa180db10792a50394b9e575e16045dd27800757660f70d5389c9efb0321a8bfaf684e1974ad22ad0387d66c5e
6
+ metadata.gz: f99a415dc0a290e33e7653c8441db1098a3e244636025ecc14b48f07e0728e43c1da6a14d0e40bd7fe142d30396ad3d14d3a4cc030bff57b2bac20c06e13b515
7
+ data.tar.gz: d9443d260d69583a2f36f1b4526dfd157f132aa6b17f68c0dc987c42a56101260208415c16a3e88abb745b1b5fc49f4e6bf1012579eff84ab9281dd8c38ba871
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Rdkafka Changelog
2
2
 
3
+ ## 0.28.0 (2026-06-03)
4
+ - [Enhancement] Bump librdkafka to `2.14.1`
5
+ - [Enhancement] Replace version-gated `Warning[:performance]` with dynamic `Warning.categories` opt-in in spec helper so new Ruby warning categories are automatically enabled without manual updates.
6
+ - [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.
7
+
8
+ ## 0.27.0 (2026-05-07)
9
+ - [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`.
10
+ - [Feature] Add `Config#describe_properties` to dump all librdkafka configuration properties (including defaults and hidden properties) as a Hash via `rd_kafka_conf_dump`.
11
+ - [Enhancement] Bump librdkafka to `2.14.0`
12
+ - [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.
13
+ - [Fix] Fix leaked queue reference in `Config#native_kafka` where `rd_kafka_queue_get_main` return value was not destroyed after passing to `rd_kafka_set_log_queue`.
14
+ - [Fix] Fix native topic partition list leak in `Consumer#position` where `tpl` was never destroyed.
15
+
3
16
  ## 0.26.0 (2026-04-02)
4
17
  - [Enhancement] Bump librdkafka to `2.13.2`
5
18
  - [Enhancement] Embed a per-file SPEC_HASH in test topic and consumer group names for tracing Kafka warnings back to specific spec files.
data/README.md CHANGED
@@ -163,7 +163,9 @@ bundle exec rake produce_messages
163
163
 
164
164
  | rdkafka-ruby | librdkafka | patches |
165
165
  |-|-|-|
166
- | 0.26.x (2026-03-30) | 2.13.2 (2026-03-30) | yes |
166
+ | 0.28.x (2026-06-03) | 2.14.1 (2026-04-15) | yes |
167
+ | 0.27.x (2026-05-07) | 2.14.0 (2026-04-01) | yes |
168
+ | 0.26.x (2026-03-30) | 2.13.2 (2026-03-02) | yes |
167
169
  | 0.25.x (2026-01-21) | 2.12.1 (2025-10-21) | yes |
168
170
  | 0.24.x (2025-10-10) | 2.11.1 (2025-08-18) | yes |
169
171
  | 0.23.x (2025-09-04) | 2.11.0 (2025-07-03) | yes |
@@ -1,7 +1,7 @@
1
1
  services:
2
2
  kafka:
3
3
  container_name: kafka
4
- image: confluentinc/cp-kafka:8.2.0
4
+ image: confluentinc/cp-kafka:8.2.1
5
5
  ports:
6
6
  - 9092:9092 # Support PLAINTEXT so we can run one docker setup for SSL and PLAINTEXT
7
7
  - 9093:9093
data/docker-compose.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  services:
2
2
  kafka:
3
3
  container_name: kafka
4
- image: confluentinc/cp-kafka:8.2.0
4
+ image: confluentinc/cp-kafka:8.2.1
5
5
 
6
6
  ports:
7
7
  - 9092:9092
data/ext/librdkafka.so CHANGED
Binary file
data/lib/rdkafka/admin.rb CHANGED
@@ -777,6 +777,9 @@ module Rdkafka
777
777
 
778
778
  raise
779
779
  ensure
780
+ Rdkafka::Bindings.rd_kafka_AdminOptions_destroy(admin_options_ptr)
781
+ Rdkafka::Bindings.rd_kafka_queue_destroy(queue_ptr)
782
+
780
783
  if configs_array_ptr
781
784
  Rdkafka::Bindings.rd_kafka_ConfigResource_destroy_array(
782
785
  configs_array_ptr,
@@ -865,6 +868,9 @@ module Rdkafka
865
868
 
866
869
  raise
867
870
  ensure
871
+ Rdkafka::Bindings.rd_kafka_AdminOptions_destroy(admin_options_ptr)
872
+ Rdkafka::Bindings.rd_kafka_queue_destroy(queue_ptr)
873
+
868
874
  if configs_array_ptr
869
875
  Rdkafka::Bindings.rd_kafka_ConfigResource_destroy_array(
870
876
  configs_array_ptr,
@@ -234,6 +234,9 @@ module Rdkafka
234
234
 
235
235
  attach_function :rd_kafka_conf_new, [], :pointer
236
236
  attach_function :rd_kafka_conf_set, [:pointer, :string, :string, :pointer, :int], :kafka_config_response
237
+ attach_function :rd_kafka_conf_dump, [:pointer, :pointer], :pointer
238
+ attach_function :rd_kafka_conf_dump_free, [:pointer, :size_t], :void
239
+ attach_function :rd_kafka_conf_destroy, [:pointer], :void
237
240
  callback :log_cb, [:pointer, :int, :string, :string], :void
238
241
  attach_function :rd_kafka_conf_set_log_cb, [:pointer, :log_cb], :void
239
242
  attach_function :rd_kafka_conf_set_opaque, [:pointer, :pointer], :void
@@ -383,6 +386,9 @@ module Rdkafka
383
386
  # More efficient for poll(0) calls in fiber schedulers.
384
387
  attach_function :rd_kafka_consumer_poll_nb, :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: false
385
388
  attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
389
+ attach_function :rd_kafka_queue_get_consumer, [:pointer], :pointer
390
+ attach_function :rd_kafka_consume_batch_queue, [:pointer, :int, :pointer, :size_t], :ssize_t, blocking: true
391
+ attach_function :rd_kafka_consume_batch_queue_nb, :rd_kafka_consume_batch_queue, [:pointer, :int, :pointer, :size_t], :ssize_t, blocking: false
386
392
  attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
387
393
  attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
388
394
  attach_function :rd_kafka_resume_partitions, [:pointer, :pointer], :int, blocking: true
@@ -285,6 +285,46 @@ module Rdkafka
285
285
  )
286
286
  end
287
287
 
288
+ # Returns all configuration properties and their current values for this config.
289
+ #
290
+ # Uses `rd_kafka_conf_dump` to retrieve every property (including defaults and
291
+ # internal properties like `client.software.name`) as a flat Hash.
292
+ #
293
+ # @note The librdkafka C API does not distinguish between producer-only, consumer-only,
294
+ # and global properties at the configuration level. All properties are returned
295
+ # regardless of the intended client type.
296
+ #
297
+ # @note The returned Hash may include sensitive values such as authentication
298
+ # credentials and key passwords. Do not log or serialize the returned data
299
+ # unless you have explicitly redacted secret entries.
300
+ #
301
+ # @return [Hash{Symbol => String}] property names mapped to their current values
302
+ #
303
+ # @raise [ConfigError] When the configuration contains invalid options
304
+ def describe_properties
305
+ config = nil
306
+ dump_ptr = nil
307
+ count = 0
308
+
309
+ config = native_config
310
+ count_ptr = Rdkafka::Bindings::SizePtr.new
311
+ dump_ptr = Rdkafka::Bindings.rd_kafka_conf_dump(config, count_ptr)
312
+
313
+ count = count_ptr[:value]
314
+ result = {}
315
+
316
+ (0...count).step(2) do |i|
317
+ key = dump_ptr.get_pointer(i * FFI::Pointer.size).read_string
318
+ value = dump_ptr.get_pointer((i + 1) * FFI::Pointer.size).read_string
319
+ result[key.to_sym] = value
320
+ end
321
+
322
+ result
323
+ ensure
324
+ Rdkafka::Bindings.rd_kafka_conf_dump_free(dump_ptr, count) if dump_ptr
325
+ Rdkafka::Bindings.rd_kafka_conf_destroy(config) if config
326
+ end
327
+
288
328
  # Error that is returned by the underlying rdkafka error if an invalid configuration option is present.
289
329
  class ConfigError < RuntimeError; end
290
330
 
@@ -364,10 +404,9 @@ module Rdkafka
364
404
  end
365
405
 
366
406
  # Redirect log to handle's queue
367
- Rdkafka::Bindings.rd_kafka_set_log_queue(
368
- handle,
369
- Rdkafka::Bindings.rd_kafka_queue_get_main(handle)
370
- )
407
+ main_queue = Rdkafka::Bindings.rd_kafka_queue_get_main(handle)
408
+ Rdkafka::Bindings.rd_kafka_set_log_queue(handle, main_queue)
409
+ Rdkafka::Bindings.rd_kafka_queue_destroy(main_queue)
371
410
 
372
411
  # Return handle which should be closed using rd_kafka_destroy after usage.
373
412
  handle
@@ -183,6 +183,11 @@ module Rdkafka
183
183
 
184
184
  @native_kafka.synchronize do |inner|
185
185
  Rdkafka::Bindings.rd_kafka_consumer_close(inner)
186
+
187
+ if @consumer_queue
188
+ Rdkafka::Bindings.rd_kafka_queue_destroy(@consumer_queue)
189
+ @consumer_queue = nil
190
+ end
186
191
  end
187
192
 
188
193
  @native_kafka.close
@@ -434,6 +439,8 @@ module Rdkafka
434
439
  end
435
440
 
436
441
  TopicPartitionList.from_native_tpl(tpl)
442
+ ensure
443
+ Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(tpl) if tpl
437
444
  end
438
445
 
439
446
  # Query broker for low (oldest/beginning) and high (newest/end) offsets for a partition.
@@ -779,6 +786,142 @@ module Rdkafka
779
786
  end
780
787
  end
781
788
 
789
+ # Poll for a batch of messages from the consumer queue in a single FFI call.
790
+ #
791
+ # This is more efficient than calling {#poll} in a loop because it crosses the FFI
792
+ # boundary only once to fetch up to `max_items` messages.
793
+ #
794
+ # The timeout controls how long to wait for the **first** message. Once any message
795
+ # is available, librdkafka fills the buffer with whatever is immediately ready and
796
+ # returns without further waiting.
797
+ #
798
+ # Error events (e.g. `:partition_eof`) are returned inline as {RdkafkaError} objects
799
+ # rather than raised, so callers receive the complete batch — both messages and errors —
800
+ # and can decide how to handle each. This is particularly useful when multiple partitions
801
+ # signal EOF simultaneously: all signals appear in the returned array rather than only
802
+ # the first one being raised and the rest silently discarded.
803
+ #
804
+ # @param timeout_ms [Integer] Timeout waiting for the first message (-1 for infinite)
805
+ # @param max_items [Integer] Maximum number of messages to return per call
806
+ # @return [Array<Message, RdkafkaError>] Batch of messages and/or error events in arrival order
807
+ # @raise [ClosedConsumerError] When called on a closed consumer
808
+ def poll_batch(timeout_ms, max_items: 100)
809
+ closed_consumer_check(__method__)
810
+
811
+ buffer = batch_buffer(max_items)
812
+ results = []
813
+
814
+ count = @native_kafka.with_inner do |_inner|
815
+ Rdkafka::Bindings.rd_kafka_consume_batch_queue(
816
+ consumer_queue,
817
+ timeout_ms,
818
+ buffer,
819
+ max_items
820
+ )
821
+ end
822
+
823
+ return results if count <= 0
824
+
825
+ i = 0
826
+ begin
827
+ while i < count
828
+ ptr = buffer.get_pointer(i * FFI::Pointer.size)
829
+
830
+ if ptr.null?
831
+ i += 1
832
+ next
833
+ end
834
+
835
+ native_message = Rdkafka::Bindings::Message.new(ptr)
836
+
837
+ if native_message[:err] != Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
838
+ results << Rdkafka::RdkafkaError.new(native_message[:err])
839
+ Rdkafka::Bindings.rd_kafka_message_destroy(ptr)
840
+ i += 1
841
+ next
842
+ end
843
+
844
+ results << Rdkafka::Consumer::Message.new(native_message)
845
+ Rdkafka::Bindings.rd_kafka_message_destroy(ptr)
846
+ i += 1
847
+ end
848
+ ensure
849
+ while i < count
850
+ ptr = buffer.get_pointer(i * FFI::Pointer.size)
851
+ Rdkafka::Bindings.rd_kafka_message_destroy(ptr) unless ptr.null?
852
+ i += 1
853
+ end
854
+ end
855
+
856
+ results
857
+ end
858
+
859
+ # Poll for a batch of messages without releasing the GVL (Global VM Lock).
860
+ #
861
+ # This is more efficient than {#poll_batch} for non-blocking poll(0) calls,
862
+ # particularly useful in fiber scheduler contexts where GVL release/reacquire
863
+ # overhead is wasteful since we don't expect to wait.
864
+ #
865
+ # @note Since the GVL is not released, a non-zero timeout_ms will block all Ruby
866
+ # threads/fibers for the duration. Use {#poll_batch} if you need a blocking wait.
867
+ #
868
+ # Error events are returned inline as {RdkafkaError} objects; see {#poll_batch} for details.
869
+ #
870
+ # @param timeout_ms [Integer] Timeout waiting for the first message (default: 0 for non-blocking)
871
+ # @param max_items [Integer] Maximum number of messages to return per call
872
+ # @return [Array<Message, RdkafkaError>] Batch of messages and/or error events in arrival order
873
+ # @raise [ClosedConsumerError] When called on a closed consumer
874
+ def poll_batch_nb(timeout_ms = 0, max_items: 100)
875
+ closed_consumer_check(__method__)
876
+
877
+ buffer = batch_buffer(max_items)
878
+ results = []
879
+
880
+ count = @native_kafka.with_inner do |_inner|
881
+ Rdkafka::Bindings.rd_kafka_consume_batch_queue_nb(
882
+ consumer_queue,
883
+ timeout_ms,
884
+ buffer,
885
+ max_items
886
+ )
887
+ end
888
+
889
+ return results if count <= 0
890
+
891
+ i = 0
892
+ begin
893
+ while i < count
894
+ ptr = buffer.get_pointer(i * FFI::Pointer.size)
895
+
896
+ if ptr.null?
897
+ i += 1
898
+ next
899
+ end
900
+
901
+ native_message = Rdkafka::Bindings::Message.new(ptr)
902
+
903
+ if native_message[:err] != Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
904
+ results << Rdkafka::RdkafkaError.new(native_message[:err])
905
+ Rdkafka::Bindings.rd_kafka_message_destroy(ptr)
906
+ i += 1
907
+ next
908
+ end
909
+
910
+ results << Rdkafka::Consumer::Message.new(native_message)
911
+ Rdkafka::Bindings.rd_kafka_message_destroy(ptr)
912
+ i += 1
913
+ end
914
+ ensure
915
+ while i < count
916
+ ptr = buffer.get_pointer(i * FFI::Pointer.size)
917
+ Rdkafka::Bindings.rd_kafka_message_destroy(ptr) unless ptr.null?
918
+ i += 1
919
+ end
920
+ end
921
+
922
+ results
923
+ end
924
+
782
925
  # Poll for new messages and yield for each received one. Iteration
783
926
  # will end when the consumer is closed.
784
927
  #
@@ -851,5 +994,24 @@ module Rdkafka
851
994
  def closed_consumer_check(method)
852
995
  raise Rdkafka::ClosedConsumerError.new(method) if closed?
853
996
  end
997
+
998
+ # Returns the consumer queue pointer, lazily initialized
999
+ # @return [FFI::Pointer] consumer queue handle
1000
+ def consumer_queue
1001
+ @consumer_queue ||= @native_kafka.with_inner do |inner|
1002
+ Rdkafka::Bindings.rd_kafka_queue_get_consumer(inner)
1003
+ end
1004
+ end
1005
+
1006
+ # Returns a reusable FFI buffer for batch polling, growing if needed
1007
+ # @param max_items [Integer] minimum buffer capacity
1008
+ # @return [FFI::MemoryPointer] pointer buffer
1009
+ def batch_buffer(max_items)
1010
+ if @batch_buffer.nil? || @batch_buffer_size < max_items
1011
+ @batch_buffer = FFI::MemoryPointer.new(:pointer, max_items)
1012
+ @batch_buffer_size = max_items
1013
+ end
1014
+ @batch_buffer
1015
+ end
854
1016
  end
855
1017
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Rdkafka
4
4
  # Current rdkafka-ruby gem version
5
- VERSION = "0.26.0"
5
+ VERSION = "0.28.0"
6
6
  # Target librdkafka version to be used
7
- LIBRDKAFKA_VERSION = "2.13.2"
7
+ LIBRDKAFKA_VERSION = "2.14.1"
8
8
  # SHA256 hash of the librdkafka source tarball for verification
9
- LIBRDKAFKA_SOURCE_SHA256 = "14972092e4115f6e99f798a7cb420cbf6daa0c73502b3c52ae42fb5b418eea8f"
9
+ LIBRDKAFKA_SOURCE_SHA256 = "bb246e754dee3560e9b42bf4e844dc05de4b146a3cae937e36301ffacdc456e7"
10
10
  end
data/package-lock.json CHANGED
@@ -286,9 +286,9 @@
286
286
  }
287
287
  },
288
288
  "node_modules/smol-toml": {
289
- "version": "1.6.0",
290
- "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz",
291
- "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==",
289
+ "version": "1.6.1",
290
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz",
291
+ "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==",
292
292
  "dev": true,
293
293
  "license": "BSD-3-Clause",
294
294
  "engines": {
@@ -312,9 +312,9 @@
312
312
  }
313
313
  },
314
314
  "node_modules/yaml": {
315
- "version": "2.8.2",
316
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
317
- "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
315
+ "version": "2.9.0",
316
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
317
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
318
318
  "dev": true,
319
319
  "license": "ISC",
320
320
  "bin": {
data/renovate.json CHANGED
@@ -85,10 +85,24 @@
85
85
  "ruby/setup-ruby",
86
86
  "ruby"
87
87
  ],
88
- "groupName": "ruby setup"
88
+ "groupName": "ruby setup",
89
+ "internalChecksFilter": "strict"
90
+ },
91
+ {
92
+ "description": "Let setup-ruby pass age gate before ruby so it is ready when the group PR is created",
93
+ "matchPackageNames": [
94
+ "ruby/setup-ruby"
95
+ ],
96
+ "minimumReleaseAge": "5 days"
89
97
  }
90
98
  ],
91
99
  "labels": [
92
100
  "dependencies"
93
- ]
101
+ ],
102
+ "lockFileMaintenance": {
103
+ "enabled": true,
104
+ "schedule": [
105
+ "before 4am on the first day of the month"
106
+ ]
107
+ }
94
108
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdkafka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.26.0
4
+ version: 0.28.0
5
5
  platform: aarch64-linux-gnu
6
6
  authors:
7
7
  - Thijs Cadier
@@ -171,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  requirements: []
174
- rubygems_version: 4.0.6
174
+ rubygems_version: 4.0.10
175
175
  specification_version: 4
176
176
  summary: The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka.
177
177
  It wraps the production-ready C client using the ffi gem and targets Kafka 1.0+