rdkafka 0.22.2 → 0.29.0

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -3
  3. data/README.md +21 -14
  4. data/Rakefile +21 -21
  5. data/bin/verify_kafka_warnings +39 -0
  6. data/dist/{librdkafka-2.8.0.tar.gz → librdkafka-2.14.2.tar.gz} +0 -0
  7. data/docker-compose-ssl.yml +35 -0
  8. data/docker-compose.yml +2 -2
  9. data/ext/Rakefile +27 -27
  10. data/lib/rdkafka/abstract_handle.rb +54 -7
  11. data/lib/rdkafka/admin/acl_binding_result.rb +5 -5
  12. data/lib/rdkafka/admin/config_binding_result.rb +2 -2
  13. data/lib/rdkafka/admin/config_resource_binding_result.rb +1 -0
  14. data/lib/rdkafka/admin/create_acl_handle.rb +10 -6
  15. data/lib/rdkafka/admin/create_acl_report.rb +3 -2
  16. data/lib/rdkafka/admin/create_partitions_handle.rb +8 -7
  17. data/lib/rdkafka/admin/create_partitions_report.rb +1 -0
  18. data/lib/rdkafka/admin/create_topic_handle.rb +8 -7
  19. data/lib/rdkafka/admin/create_topic_report.rb +3 -0
  20. data/lib/rdkafka/admin/delete_acl_handle.rb +9 -8
  21. data/lib/rdkafka/admin/delete_acl_report.rb +5 -3
  22. data/lib/rdkafka/admin/delete_groups_handle.rb +10 -7
  23. data/lib/rdkafka/admin/delete_groups_report.rb +3 -0
  24. data/lib/rdkafka/admin/delete_topic_handle.rb +8 -7
  25. data/lib/rdkafka/admin/delete_topic_report.rb +3 -0
  26. data/lib/rdkafka/admin/describe_acl_handle.rb +9 -8
  27. data/lib/rdkafka/admin/describe_acl_report.rb +5 -3
  28. data/lib/rdkafka/admin/describe_configs_handle.rb +7 -10
  29. data/lib/rdkafka/admin/describe_configs_report.rb +8 -6
  30. data/lib/rdkafka/admin/incremental_alter_configs_handle.rb +7 -10
  31. data/lib/rdkafka/admin/incremental_alter_configs_report.rb +8 -6
  32. data/lib/rdkafka/admin/list_offsets_handle.rb +31 -0
  33. data/lib/rdkafka/admin/list_offsets_report.rb +51 -0
  34. data/lib/rdkafka/admin.rb +357 -159
  35. data/lib/rdkafka/bindings.rb +205 -111
  36. data/lib/rdkafka/callbacks/base_handler.rb +62 -0
  37. data/lib/rdkafka/callbacks/create_acl_handler.rb +37 -0
  38. data/lib/rdkafka/callbacks/create_partitions_handler.rb +37 -0
  39. data/lib/rdkafka/callbacks/create_topic_handler.rb +37 -0
  40. data/lib/rdkafka/callbacks/delete_acl_handler.rb +42 -0
  41. data/lib/rdkafka/callbacks/delete_groups_handler.rb +37 -0
  42. data/lib/rdkafka/callbacks/delete_topic_handler.rb +37 -0
  43. data/lib/rdkafka/callbacks/describe_acl_handler.rb +35 -0
  44. data/lib/rdkafka/callbacks/describe_configs_handler.rb +42 -0
  45. data/lib/rdkafka/callbacks/incremental_alter_configs_handler.rb +42 -0
  46. data/lib/rdkafka/callbacks/list_offsets_handler.rb +42 -0
  47. data/lib/rdkafka/callbacks.rb +125 -216
  48. data/lib/rdkafka/config.rb +126 -66
  49. data/lib/rdkafka/consumer/headers.rb +22 -7
  50. data/lib/rdkafka/consumer/message.rb +12 -11
  51. data/lib/rdkafka/consumer/partition.rb +15 -4
  52. data/lib/rdkafka/consumer/topic_partition_list.rb +64 -38
  53. data/lib/rdkafka/consumer.rb +513 -59
  54. data/lib/rdkafka/defaults.rb +125 -0
  55. data/lib/rdkafka/error.rb +40 -14
  56. data/lib/rdkafka/helpers/metadata.rb +29 -0
  57. data/lib/rdkafka/helpers/oauth.rb +45 -13
  58. data/lib/rdkafka/helpers/time.rb +5 -0
  59. data/lib/rdkafka/metadata.rb +128 -37
  60. data/lib/rdkafka/native_kafka.rb +91 -8
  61. data/lib/rdkafka/producer/delivery_handle.rb +6 -6
  62. data/lib/rdkafka/producer/delivery_report.rb +10 -6
  63. data/lib/rdkafka/producer/partitions_count_cache.rb +51 -55
  64. data/lib/rdkafka/producer.rb +193 -95
  65. data/lib/rdkafka/version.rb +6 -3
  66. data/lib/rdkafka.rb +15 -0
  67. data/package-lock.json +331 -0
  68. data/package.json +9 -0
  69. data/rdkafka.gemspec +58 -36
  70. data/renovate.json +39 -23
  71. metadata +39 -125
  72. data/.github/CODEOWNERS +0 -3
  73. data/.github/FUNDING.yml +0 -1
  74. data/.github/workflows/ci_linux_x86_64_gnu.yml +0 -271
  75. data/.github/workflows/ci_linux_x86_64_musl.yml +0 -194
  76. data/.github/workflows/ci_macos_arm64.yml +0 -284
  77. data/.github/workflows/push_linux_x86_64_gnu.yml +0 -65
  78. data/.github/workflows/push_linux_x86_64_musl.yml +0 -79
  79. data/.github/workflows/push_macos_arm64.yml +0 -54
  80. data/.github/workflows/push_ruby.yml +0 -37
  81. data/.github/workflows/verify-action-pins.yml +0 -16
  82. data/.gitignore +0 -14
  83. data/.rspec +0 -2
  84. data/.ruby-gemset +0 -1
  85. data/.ruby-version +0 -1
  86. data/.yardopts +0 -2
  87. data/Gemfile +0 -5
  88. data/ext/README.md +0 -19
  89. data/ext/build_common.sh +0 -361
  90. data/ext/build_linux_x86_64_gnu.sh +0 -306
  91. data/ext/build_linux_x86_64_musl.sh +0 -763
  92. data/ext/build_macos_arm64.sh +0 -550
  93. data/spec/rdkafka/abstract_handle_spec.rb +0 -117
  94. data/spec/rdkafka/admin/create_acl_handle_spec.rb +0 -56
  95. data/spec/rdkafka/admin/create_acl_report_spec.rb +0 -18
  96. data/spec/rdkafka/admin/create_topic_handle_spec.rb +0 -52
  97. data/spec/rdkafka/admin/create_topic_report_spec.rb +0 -16
  98. data/spec/rdkafka/admin/delete_acl_handle_spec.rb +0 -85
  99. data/spec/rdkafka/admin/delete_acl_report_spec.rb +0 -72
  100. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +0 -52
  101. data/spec/rdkafka/admin/delete_topic_report_spec.rb +0 -16
  102. data/spec/rdkafka/admin/describe_acl_handle_spec.rb +0 -85
  103. data/spec/rdkafka/admin/describe_acl_report_spec.rb +0 -73
  104. data/spec/rdkafka/admin_spec.rb +0 -971
  105. data/spec/rdkafka/bindings_spec.rb +0 -199
  106. data/spec/rdkafka/callbacks_spec.rb +0 -20
  107. data/spec/rdkafka/config_spec.rb +0 -258
  108. data/spec/rdkafka/consumer/headers_spec.rb +0 -73
  109. data/spec/rdkafka/consumer/message_spec.rb +0 -139
  110. data/spec/rdkafka/consumer/partition_spec.rb +0 -57
  111. data/spec/rdkafka/consumer/topic_partition_list_spec.rb +0 -248
  112. data/spec/rdkafka/consumer_spec.rb +0 -1274
  113. data/spec/rdkafka/error_spec.rb +0 -89
  114. data/spec/rdkafka/metadata_spec.rb +0 -79
  115. data/spec/rdkafka/native_kafka_spec.rb +0 -130
  116. data/spec/rdkafka/producer/delivery_handle_spec.rb +0 -45
  117. data/spec/rdkafka/producer/delivery_report_spec.rb +0 -25
  118. data/spec/rdkafka/producer/partitions_count_cache_spec.rb +0 -359
  119. data/spec/rdkafka/producer_spec.rb +0 -1345
  120. data/spec/spec_helper.rb +0 -195
@@ -5,9 +5,7 @@ module Rdkafka
5
5
  class Producer
6
6
  include Helpers::Time
7
7
  include Helpers::OAuth
8
-
9
- # Empty hash used as a default
10
- EMPTY_HASH = {}.freeze
8
+ include Helpers::Metadata
11
9
 
12
10
  # @private
13
11
  @@partitions_count_cache = PartitionsCountCache.new
@@ -17,10 +15,9 @@ module Rdkafka
17
15
  # then. Since the partitions count can only grow and should be same for all consumers and
18
16
  # producers, we can use a global cache as long as we ensure that updates only move up.
19
17
  #
18
+ # @return [Rdkafka::Producer::PartitionsCountCache]
20
19
  # @note It is critical to remember, that not all users may have statistics callbacks enabled,
21
20
  # hence we should not make assumption that this cache is always updated from the stats.
22
- #
23
- # @return [Rdkafka::Producer::PartitionsCountCache]
24
21
  def self.partitions_count_cache
25
22
  @@partitions_count_cache
26
23
  end
@@ -30,6 +27,9 @@ module Rdkafka
30
27
  @@partitions_count_cache = partitions_count_cache
31
28
  end
32
29
 
30
+ # Empty hash used as a default
31
+ EMPTY_HASH = {}.freeze
32
+
33
33
  private_constant :EMPTY_HASH
34
34
 
35
35
  # Raised when there was a critical issue when invoking rd_kafka_topic_new
@@ -64,12 +64,13 @@ module Rdkafka
64
64
  end
65
65
 
66
66
  # Sets alternative set of configuration details that can be set per topic
67
- # @note It is not allowed to re-set the same topic config twice because of the underlying
68
- # librdkafka caching
67
+ #
69
68
  # @param topic [String] The topic name
70
69
  # @param config [Hash] config we want to use per topic basis
71
70
  # @param config_hash [Integer] hash of the config. We expect it here instead of computing it,
72
71
  # because it is already computed during the retrieval attempt in the `#produce` flow.
72
+ # @note It is not allowed to re-set the same topic config twice because of the underlying
73
+ # librdkafka caching
73
74
  def set_topic_config(topic, config, config_hash)
74
75
  # Ensure lock on topic reference just in case
75
76
  @native_kafka.with_inner do |inner|
@@ -80,25 +81,31 @@ module Rdkafka
80
81
 
81
82
  # If config is empty, we create an empty reference that will be used with defaults
82
83
  rd_topic_config = if config.empty?
83
- nil
84
- else
85
- Rdkafka::Bindings.rd_kafka_topic_conf_new.tap do |topic_config|
86
- config.each do |key, value|
87
- error_buffer = FFI::MemoryPointer.new(:char, 256)
88
- result = Rdkafka::Bindings.rd_kafka_topic_conf_set(
89
- topic_config,
90
- key.to_s,
91
- value.to_s,
92
- error_buffer,
93
- 256
94
- )
95
-
96
- unless result == :config_ok
97
- raise Config::ConfigError.new(error_buffer.read_string)
98
- end
99
- end
100
- end
101
- end
84
+ nil
85
+ else
86
+ Rdkafka::Bindings.rd_kafka_topic_conf_new.tap do |topic_config|
87
+ config.each do |key, value|
88
+ error_buffer = FFI::MemoryPointer.new(:char, 256)
89
+ result = Rdkafka::Bindings.rd_kafka_topic_conf_set(
90
+ topic_config,
91
+ key.to_s,
92
+ value.to_s,
93
+ error_buffer,
94
+ 256
95
+ )
96
+
97
+ unless result == :config_ok
98
+ # rd_kafka_topic_new has not been called yet, so librdkafka has not taken
99
+ # ownership of the config. Destroy it ourselves before raising, otherwise the
100
+ # partially built rd_kafka_topic_conf_t leaks. (On the rd_kafka_topic_new path
101
+ # librdkafka frees the conf on both success and failure, so we never destroy it
102
+ # there.)
103
+ Rdkafka::Bindings.rd_kafka_topic_conf_destroy(topic_config)
104
+ raise Config::ConfigError.new(error_buffer.read_string)
105
+ end
106
+ end
107
+ end
108
+ end
102
109
 
103
110
  topic_handle = Bindings.rd_kafka_topic_new(inner, topic, rd_topic_config)
104
111
 
@@ -122,11 +129,30 @@ module Rdkafka
122
129
  end
123
130
  end
124
131
 
132
+ # Enable IO event notifications for fiber scheduler integration
133
+ # When delivery confirmations arrive, librdkafka will write to your FD
134
+ #
135
+ # @param fd [Integer] file descriptor to signal (from IO.pipe or eventfd)
136
+ # @param payload [String] data to write to fd (default: "\x01")
137
+ # @return [nil]
138
+ # @raise [ClosedInnerError] when the producer is closed
139
+ def enable_queue_io_events(fd, payload = "\x01")
140
+ @native_kafka.enable_main_queue_io_events(fd, payload)
141
+ end
142
+
143
+ # Enable IO event notifications for background events
144
+ # @param fd [Integer] file descriptor to signal (from IO.pipe or eventfd)
145
+ # @param payload [String] data to write to fd (default: "\x01")
146
+ # @return [nil]
147
+ # @raise [ClosedInnerError] when the producer is closed
148
+ def enable_background_queue_io_events(fd, payload = "\x01")
149
+ @native_kafka.enable_background_queue_io_events(fd, payload)
150
+ end
151
+
125
152
  # Set a callback that will be called every time a message is successfully produced.
126
153
  # The callback is called with a {DeliveryReport} and {DeliveryHandle}
127
154
  #
128
- # @param callback [Proc, #call] The callback
129
- #
155
+ # @param callback [Proc, #call] callable object to handle delivery reports
130
156
  # @return [nil]
131
157
  def delivery_callback=(callback)
132
158
  raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call)
@@ -168,7 +194,7 @@ module Rdkafka
168
194
  # should be no other errors.
169
195
  #
170
196
  # @note For `timed_out` we do not raise an error to keep it backwards compatible
171
- def flush(timeout_ms=5_000)
197
+ def flush(timeout_ms = Defaults::PRODUCER_FLUSH_TIMEOUT_MS)
172
198
  closed_producer_check(__method__)
173
199
 
174
200
  code = nil
@@ -208,11 +234,76 @@ module Rdkafka
208
234
  code.zero? || raise(Rdkafka::RdkafkaError.new(code))
209
235
 
210
236
  # Wait for the purge to affect everything
211
- sleep(0.001) until flush(100)
237
+ sleep(Defaults::PRODUCER_PURGE_SLEEP_INTERVAL_MS / 1000.0) until flush(Defaults::PRODUCER_PURGE_FLUSH_TIMEOUT_MS)
212
238
 
213
239
  true
214
240
  end
215
241
 
242
+ # Returns the number of messages and requests waiting to be sent to the broker as well as
243
+ # delivery reports queued for the application.
244
+ #
245
+ # This provides visibility into the producer's internal queue depth, useful for:
246
+ # - Monitoring producer backpressure
247
+ # - Implementing custom flow control
248
+ # - Debugging message delivery issues
249
+ # - Graceful shutdown logic (wait until queue is empty)
250
+ #
251
+ # @return [Integer] the number of messages in the queue
252
+ # @raise [Rdkafka::ClosedProducerError] if called on a closed producer
253
+ #
254
+ # @note This method is thread-safe as it uses the @native_kafka.with_inner synchronization
255
+ #
256
+ # @example
257
+ # producer.queue_size #=> 42
258
+ def queue_size
259
+ closed_producer_check(__method__)
260
+
261
+ @native_kafka.with_inner do |inner|
262
+ Rdkafka::Bindings.rd_kafka_outq_len(inner)
263
+ end
264
+ end
265
+
266
+ alias_method :queue_length, :queue_size
267
+
268
+ # Polls for events in a non-blocking loop, yielding the count after each iteration.
269
+ #
270
+ # This method processes delivery callbacks in a single GVL/mutex session, which is more
271
+ # efficient than repeated individual polls. It uses non-blocking polls internally
272
+ # (no GVL release between polls).
273
+ #
274
+ # Yields the count of events processed after each poll iteration, allowing the caller
275
+ # to implement timeout or other termination logic by returning `:stop`.
276
+ #
277
+ # @yield [count] Called after each poll iteration
278
+ # @yieldparam count [Integer] Number of events processed in this iteration
279
+ # @yieldreturn [Symbol, Object] Return `:stop` to break the loop, any other value continues
280
+ # @return [nil]
281
+ # @raise [Rdkafka::ClosedProducerError] if called on a closed producer
282
+ #
283
+ # @note This method holds the inner lock until the queue is empty or `:stop` is returned.
284
+ # Other producer operations (produce, close, etc.) will wait until this method returns.
285
+ # @note This method is thread-safe as it uses @native_kafka.with_inner synchronization
286
+ #
287
+ # @example Drain all pending callbacks
288
+ # producer.events_poll_nb_each { |_count| }
289
+ #
290
+ # @example With timeout control
291
+ # deadline = monotonic_now + timeout_ms
292
+ # producer.events_poll_nb_each do |_count|
293
+ # :stop if monotonic_now >= deadline
294
+ # end
295
+ def events_poll_nb_each
296
+ closed_producer_check(__method__)
297
+
298
+ @native_kafka.with_inner do |inner|
299
+ loop do
300
+ count = Rdkafka::Bindings.rd_kafka_poll_nb(inner, 0)
301
+ break if count.zero?
302
+ break if yield(count) == :stop
303
+ end
304
+ end
305
+ end
306
+
216
307
  # Partition count for a given topic.
217
308
  #
218
309
  # @param topic [String] The topic name.
@@ -237,15 +328,16 @@ module Rdkafka
237
328
  topic_metadata = ::Rdkafka::Metadata.new(inner, topic).topics&.first
238
329
  end
239
330
 
240
- topic_metadata ? topic_metadata[:partition_count] : -1
241
- end
242
- rescue Rdkafka::RdkafkaError => e
243
- # If the topic does not exist, it will be created or if not allowed another error will be
244
- # raised. We here return -1 so this can happen without early error happening on metadata
245
- # discovery.
246
- return -1 if e.code == :unknown_topic_or_part
331
+ topic_metadata ? topic_metadata[:partition_count] : Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
332
+ rescue Rdkafka::RdkafkaError => e
333
+ # A missing topic is an expected, cacheable outcome (the topic may be auto-created on
334
+ # produce, or simply not exist yet). Returning RD_KAFKA_PARTITION_UA from inside the block
335
+ # caches it, so we don't re-run a blocking metadata query on every produce(partition_key:)
336
+ # to that topic. Anything else is a real error and is re-raised.
337
+ raise(e) unless e.code == :unknown_topic_or_part
247
338
 
248
- raise(e)
339
+ Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
340
+ end
249
341
  end
250
342
 
251
343
  # Produces a message to a Kafka topic. The message is added to rdkafka's queue, call {DeliveryHandle#wait wait} on the returned delivery handle to make sure it is delivered.
@@ -254,14 +346,15 @@ module Rdkafka
254
346
  # When a timestamp is provided this is used instead of the auto-generated timestamp.
255
347
  #
256
348
  # @param topic [String] The topic to produce to
257
- # @param payload [String,nil] The message's payload
258
- # @param key [String, nil] The message's key
259
- # @param partition [Integer,nil] Optional partition to produce to
349
+ # @param payload [String, nil]
350
+ # @param key [String, nil]
351
+ # @param partition [Integer, nil] Optional partition to produce to
260
352
  # @param partition_key [String, nil] Optional partition key based on which partition assignment can happen
261
- # @param timestamp [Time,Integer,nil] Optional timestamp of this message. Integer timestamp is in milliseconds since Jan 1 1970.
262
- # @param headers [Hash<String,String|Array<String>>] Optional message headers. Values can be either a single string or an array of strings to support duplicate headers per KIP-82
353
+ # @param timestamp [Time, Integer, nil] Optional timestamp of this message. Integer timestamp is in milliseconds since Jan 1 1970.
354
+ # @param headers [Hash{String => String, Array<String>}] Optional message headers. Values can be either a single string or an array of strings to support duplicate headers per KIP-82
263
355
  # @param label [Object, nil] a label that can be assigned when producing a message that will be part of the delivery handle and the delivery report
264
356
  # @param topic_config [Hash] topic config for given message dispatch. Allows to send messages to topics with different configuration
357
+ # @param partitioner [String] name of the partitioner to use
265
358
  #
266
359
  # @return [DeliveryHandle] Delivery handle that can be used to wait for the result of producing this message
267
360
  #
@@ -284,17 +377,17 @@ module Rdkafka
284
377
 
285
378
  # Get payload length
286
379
  payload_size = if payload.nil?
287
- 0
288
- else
289
- payload.bytesize
290
- end
380
+ 0
381
+ else
382
+ payload.bytesize
383
+ end
291
384
 
292
385
  # Get key length
293
386
  key_size = if key.nil?
294
- 0
295
- else
296
- key.bytesize
297
- end
387
+ 0
388
+ else
389
+ key.bytesize
390
+ end
298
391
 
299
392
  topic_config_hash = topic_config.hash
300
393
 
@@ -311,50 +404,52 @@ module Rdkafka
311
404
  selected_partitioner = @topics_configs.dig(topic, topic_config_hash, :partitioner) || partitioner
312
405
 
313
406
  # If the topic is not present, set to -1
314
- partition = Rdkafka::Bindings.partitioner(
315
- topic_ref,
316
- partition_key,
317
- partition_count,
318
- selected_partitioner) if partition_count.positive?
407
+ if partition_count.positive?
408
+ partition = Rdkafka::Bindings.partitioner(
409
+ topic_ref,
410
+ partition_key,
411
+ partition_count,
412
+ selected_partitioner
413
+ )
414
+ end
319
415
  end
320
416
 
321
- # If partition is nil, use -1 to let librdafka set the partition randomly or
417
+ # If partition is nil, use RD_KAFKA_PARTITION_UA to let librdafka set the partition randomly or
322
418
  # based on the key when present.
323
- partition ||= -1
419
+ partition ||= Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
324
420
 
325
- # If timestamp is nil use 0 and let Kafka set one. If an integer or time
326
- # use it.
421
+ # If timestamp is nil use 0 and let Kafka set one. If an integer or time use it.
327
422
  raw_timestamp = if timestamp.nil?
328
- 0
329
- elsif timestamp.is_a?(Integer)
330
- timestamp
331
- elsif timestamp.is_a?(Time)
332
- (timestamp.to_i * 1000) + (timestamp.usec / 1000)
333
- else
334
- raise TypeError.new("Timestamp has to be nil, an Integer or a Time")
335
- end
423
+ 0
424
+ elsif timestamp.is_a?(Integer)
425
+ timestamp
426
+ elsif timestamp.is_a?(Time)
427
+ (timestamp.to_i * 1000) + (timestamp.usec / 1000)
428
+ else
429
+ raise TypeError.new("Timestamp has to be nil, an Integer or a Time")
430
+ end
336
431
 
337
432
  delivery_handle = DeliveryHandle.new
338
433
  delivery_handle.label = label
339
434
  delivery_handle.topic = topic
340
435
  delivery_handle[:pending] = true
341
- delivery_handle[:response] = -1
342
- delivery_handle[:partition] = -1
343
- delivery_handle[:offset] = -1
436
+ delivery_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
437
+ delivery_handle[:partition] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
438
+ delivery_handle[:offset] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
344
439
  DeliveryHandle.register(delivery_handle)
345
440
 
346
- args = [
347
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_RKT, :pointer, topic_ref,
348
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_MSGFLAGS, :int, Rdkafka::Bindings::RD_KAFKA_MSG_F_COPY,
349
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_VALUE, :buffer_in, payload, :size_t, payload_size,
350
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_KEY, :buffer_in, key, :size_t, key_size,
351
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_PARTITION, :int32, partition,
352
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_TIMESTAMP, :int64, raw_timestamp,
353
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_OPAQUE, :pointer, delivery_handle,
354
- ]
355
-
356
- if headers
357
- headers.each do |key0, value0|
441
+ begin
442
+ args = [
443
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_RKT, :pointer, topic_ref,
444
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_MSGFLAGS, :int, Rdkafka::Bindings::RD_KAFKA_MSG_F_COPY,
445
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_VALUE, :buffer_in, payload, :size_t, payload_size,
446
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_KEY, :buffer_in, key, :size_t, key_size,
447
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_PARTITION, :int32, partition,
448
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_TIMESTAMP, :int64, raw_timestamp,
449
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_OPAQUE, :pointer, delivery_handle
450
+ ]
451
+
452
+ headers&.each do |key0, value0|
358
453
  key = key0.to_s
359
454
  if value0.is_a?(Array)
360
455
  # Handle array of values per KIP-82
@@ -374,22 +469,24 @@ module Rdkafka
374
469
  args << :size_t << value.bytesize
375
470
  end
376
471
  end
377
- end
378
472
 
379
- args << :int << Rdkafka::Bindings::RD_KAFKA_VTYPE_END
473
+ args << :int << Rdkafka::Bindings::RD_KAFKA_VTYPE_END
380
474
 
381
- # Produce the message
382
- response = @native_kafka.with_inner do |inner|
383
- Rdkafka::Bindings.rd_kafka_producev(
384
- inner,
385
- *args
386
- )
387
- end
475
+ # Produce the message
476
+ response = @native_kafka.with_inner do |inner|
477
+ Rdkafka::Bindings.rd_kafka_producev(
478
+ inner,
479
+ *args
480
+ )
481
+ end
388
482
 
389
- # Raise error if the produce call was not successful
390
- if response != 0
483
+ # Raise error if the produce call was not successful
484
+ if response != Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
485
+ raise RdkafkaError.new(response)
486
+ end
487
+ rescue Exception
391
488
  DeliveryHandle.remove(delivery_handle.to_ptr.address)
392
- raise RdkafkaError.new(response)
489
+ raise
393
490
  end
394
491
 
395
492
  delivery_handle
@@ -431,5 +528,6 @@ module Rdkafka
431
528
  def closed_producer_check(method)
432
529
  raise Rdkafka::ClosedProducerError.new(method) if closed?
433
530
  end
531
+ alias_method :closed_check, :closed_producer_check
434
532
  end
435
533
  end
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rdkafka
4
- VERSION = "0.22.2"
5
- LIBRDKAFKA_VERSION = "2.8.0"
6
- LIBRDKAFKA_SOURCE_SHA256 = "5bd1c46f63265f31c6bfcedcde78703f77d28238eadf23821c2b43fc30be3e25"
4
+ # Current rdkafka-ruby gem version
5
+ VERSION = "0.29.0"
6
+ # Target librdkafka version to be used
7
+ LIBRDKAFKA_VERSION = "2.14.2"
8
+ # SHA256 hash of the librdkafka source tarball for verification
9
+ LIBRDKAFKA_SOURCE_SHA256 = "d7eec9c31c817fa44402f679c252dfbf97e4c338a849a25c3579a31fd127beb8"
7
10
  end
data/lib/rdkafka.rb CHANGED
@@ -8,6 +8,8 @@ require "json"
8
8
  require "rdkafka/version"
9
9
  require "rdkafka/helpers/time"
10
10
  require "rdkafka/helpers/oauth"
11
+ require "rdkafka/helpers/metadata"
12
+ require "rdkafka/defaults"
11
13
  require "rdkafka/abstract_handle"
12
14
  require "rdkafka/admin"
13
15
  require "rdkafka/admin/create_topic_handle"
@@ -28,11 +30,24 @@ require "rdkafka/admin/describe_configs_handle"
28
30
  require "rdkafka/admin/describe_configs_report"
29
31
  require "rdkafka/admin/incremental_alter_configs_handle"
30
32
  require "rdkafka/admin/incremental_alter_configs_report"
33
+ require "rdkafka/admin/list_offsets_handle"
34
+ require "rdkafka/admin/list_offsets_report"
31
35
  require "rdkafka/admin/acl_binding_result"
32
36
  require "rdkafka/admin/config_binding_result"
33
37
  require "rdkafka/admin/config_resource_binding_result"
34
38
  require "rdkafka/bindings"
35
39
  require "rdkafka/callbacks"
40
+ require "rdkafka/callbacks/base_handler"
41
+ require "rdkafka/callbacks/create_topic_handler"
42
+ require "rdkafka/callbacks/delete_topic_handler"
43
+ require "rdkafka/callbacks/create_partitions_handler"
44
+ require "rdkafka/callbacks/delete_groups_handler"
45
+ require "rdkafka/callbacks/create_acl_handler"
46
+ require "rdkafka/callbacks/delete_acl_handler"
47
+ require "rdkafka/callbacks/describe_acl_handler"
48
+ require "rdkafka/callbacks/describe_configs_handler"
49
+ require "rdkafka/callbacks/incremental_alter_configs_handler"
50
+ require "rdkafka/callbacks/list_offsets_handler"
36
51
  require "rdkafka/config"
37
52
  require "rdkafka/consumer"
38
53
  require "rdkafka/consumer/headers"