rdkafka 0.22.2 → 0.27.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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -3
  3. data/Gemfile +8 -0
  4. data/Gemfile.lint +14 -0
  5. data/Gemfile.lint.lock +123 -0
  6. data/README.md +19 -14
  7. data/Rakefile +21 -21
  8. data/bin/verify_kafka_warnings +39 -0
  9. data/dist/{librdkafka-2.8.0.tar.gz → librdkafka-2.14.0.tar.gz} +0 -0
  10. data/docker-compose-ssl.yml +35 -0
  11. data/docker-compose.yml +2 -2
  12. data/ext/Rakefile +27 -27
  13. data/lib/rdkafka/abstract_handle.rb +23 -5
  14. data/lib/rdkafka/admin/acl_binding_result.rb +5 -5
  15. data/lib/rdkafka/admin/config_resource_binding_result.rb +1 -0
  16. data/lib/rdkafka/admin/create_acl_handle.rb +7 -4
  17. data/lib/rdkafka/admin/create_acl_report.rb +3 -2
  18. data/lib/rdkafka/admin/create_partitions_handle.rb +8 -5
  19. data/lib/rdkafka/admin/create_partitions_report.rb +1 -0
  20. data/lib/rdkafka/admin/create_topic_handle.rb +8 -5
  21. data/lib/rdkafka/admin/create_topic_report.rb +3 -0
  22. data/lib/rdkafka/admin/delete_acl_handle.rb +9 -6
  23. data/lib/rdkafka/admin/delete_acl_report.rb +5 -3
  24. data/lib/rdkafka/admin/delete_groups_handle.rb +10 -5
  25. data/lib/rdkafka/admin/delete_groups_report.rb +3 -0
  26. data/lib/rdkafka/admin/delete_topic_handle.rb +8 -5
  27. data/lib/rdkafka/admin/delete_topic_report.rb +3 -0
  28. data/lib/rdkafka/admin/describe_acl_handle.rb +9 -6
  29. data/lib/rdkafka/admin/describe_acl_report.rb +5 -3
  30. data/lib/rdkafka/admin/describe_configs_handle.rb +7 -4
  31. data/lib/rdkafka/admin/describe_configs_report.rb +7 -1
  32. data/lib/rdkafka/admin/incremental_alter_configs_handle.rb +7 -4
  33. data/lib/rdkafka/admin/incremental_alter_configs_report.rb +7 -1
  34. data/lib/rdkafka/admin/list_offsets_handle.rb +36 -0
  35. data/lib/rdkafka/admin/list_offsets_report.rb +51 -0
  36. data/lib/rdkafka/admin.rb +301 -135
  37. data/lib/rdkafka/bindings.rb +199 -110
  38. data/lib/rdkafka/callbacks.rb +124 -21
  39. data/lib/rdkafka/config.rb +81 -33
  40. data/lib/rdkafka/consumer/headers.rb +3 -2
  41. data/lib/rdkafka/consumer/message.rb +12 -11
  42. data/lib/rdkafka/consumer/partition.rb +8 -4
  43. data/lib/rdkafka/consumer/topic_partition_list.rb +21 -17
  44. data/lib/rdkafka/consumer.rb +397 -45
  45. data/lib/rdkafka/defaults.rb +106 -0
  46. data/lib/rdkafka/error.rb +40 -14
  47. data/lib/rdkafka/helpers/oauth.rb +45 -13
  48. data/lib/rdkafka/helpers/time.rb +5 -0
  49. data/lib/rdkafka/metadata.rb +45 -21
  50. data/lib/rdkafka/native_kafka.rb +89 -4
  51. data/lib/rdkafka/producer/delivery_handle.rb +5 -5
  52. data/lib/rdkafka/producer/delivery_report.rb +10 -6
  53. data/lib/rdkafka/producer/partitions_count_cache.rb +29 -19
  54. data/lib/rdkafka/producer.rb +168 -82
  55. data/lib/rdkafka/version.rb +6 -3
  56. data/lib/rdkafka.rb +3 -0
  57. data/package-lock.json +331 -0
  58. data/package.json +9 -0
  59. data/rdkafka.gemspec +57 -36
  60. data/renovate.json +29 -24
  61. metadata +29 -124
  62. data/.github/CODEOWNERS +0 -3
  63. data/.github/FUNDING.yml +0 -1
  64. data/.github/workflows/ci_linux_x86_64_gnu.yml +0 -271
  65. data/.github/workflows/ci_linux_x86_64_musl.yml +0 -194
  66. data/.github/workflows/ci_macos_arm64.yml +0 -284
  67. data/.github/workflows/push_linux_x86_64_gnu.yml +0 -65
  68. data/.github/workflows/push_linux_x86_64_musl.yml +0 -79
  69. data/.github/workflows/push_macos_arm64.yml +0 -54
  70. data/.github/workflows/push_ruby.yml +0 -37
  71. data/.github/workflows/verify-action-pins.yml +0 -16
  72. data/.gitignore +0 -14
  73. data/.rspec +0 -2
  74. data/.ruby-gemset +0 -1
  75. data/.ruby-version +0 -1
  76. data/.yardopts +0 -2
  77. data/ext/README.md +0 -19
  78. data/ext/build_common.sh +0 -361
  79. data/ext/build_linux_x86_64_gnu.sh +0 -306
  80. data/ext/build_linux_x86_64_musl.sh +0 -763
  81. data/ext/build_macos_arm64.sh +0 -550
  82. data/spec/rdkafka/abstract_handle_spec.rb +0 -117
  83. data/spec/rdkafka/admin/create_acl_handle_spec.rb +0 -56
  84. data/spec/rdkafka/admin/create_acl_report_spec.rb +0 -18
  85. data/spec/rdkafka/admin/create_topic_handle_spec.rb +0 -52
  86. data/spec/rdkafka/admin/create_topic_report_spec.rb +0 -16
  87. data/spec/rdkafka/admin/delete_acl_handle_spec.rb +0 -85
  88. data/spec/rdkafka/admin/delete_acl_report_spec.rb +0 -72
  89. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +0 -52
  90. data/spec/rdkafka/admin/delete_topic_report_spec.rb +0 -16
  91. data/spec/rdkafka/admin/describe_acl_handle_spec.rb +0 -85
  92. data/spec/rdkafka/admin/describe_acl_report_spec.rb +0 -73
  93. data/spec/rdkafka/admin_spec.rb +0 -971
  94. data/spec/rdkafka/bindings_spec.rb +0 -199
  95. data/spec/rdkafka/callbacks_spec.rb +0 -20
  96. data/spec/rdkafka/config_spec.rb +0 -258
  97. data/spec/rdkafka/consumer/headers_spec.rb +0 -73
  98. data/spec/rdkafka/consumer/message_spec.rb +0 -139
  99. data/spec/rdkafka/consumer/partition_spec.rb +0 -57
  100. data/spec/rdkafka/consumer/topic_partition_list_spec.rb +0 -248
  101. data/spec/rdkafka/consumer_spec.rb +0 -1274
  102. data/spec/rdkafka/error_spec.rb +0 -89
  103. data/spec/rdkafka/metadata_spec.rb +0 -79
  104. data/spec/rdkafka/native_kafka_spec.rb +0 -130
  105. data/spec/rdkafka/producer/delivery_handle_spec.rb +0 -45
  106. data/spec/rdkafka/producer/delivery_report_spec.rb +0 -25
  107. data/spec/rdkafka/producer/partitions_count_cache_spec.rb +0 -359
  108. data/spec/rdkafka/producer_spec.rb +0 -1345
  109. data/spec/spec_helper.rb +0 -195
@@ -17,9 +17,9 @@ module Rdkafka
17
17
  #
18
18
  # 2. Edge case handling
19
19
  # If a user configures `statistics.interval.ms` much higher than the default cache TTL
20
- # (30 seconds), the cache will still function correctly. When statistics updates don't
21
- # occur frequently enough, the cache entries will expire naturally, triggering a
22
- # blocking refresh when needed.
20
+ # ({Defaults::PARTITIONS_COUNT_CACHE_TTL_MS}ms), the cache will still function correctly.
21
+ # When statistics updates don't occur frequently enough, the cache entries will expire
22
+ # naturally, triggering a blocking refresh when needed.
23
23
  #
24
24
  # 3. User configuration awareness
25
25
  # The cache respects user-defined settings. If `topic.metadata.refresh.interval.ms` is
@@ -46,22 +46,32 @@ module Rdkafka
46
46
  class PartitionsCountCache
47
47
  include Helpers::Time
48
48
 
49
- # Default time-to-live for cached partition counts in seconds
50
- #
51
- # @note This default was chosen to balance freshness of metadata with performance
52
- # optimization. Most Kafka cluster topology changes are planned operations, making 30
53
- # seconds a reasonable compromise.
54
- DEFAULT_TTL = 30
55
-
56
49
  # Creates a new partition count cache
57
50
  #
58
- # @param ttl [Integer] Time-to-live in seconds for cached values
59
- def initialize(ttl = DEFAULT_TTL)
51
+ # @param ttl [Integer, nil] DEPRECATED: Use ttl_ms instead.
52
+ # Time-to-live in seconds for cached values. Will be removed in v1.0.0.
53
+ # @param ttl_ms [Integer, nil] Time-to-live in milliseconds for cached values.
54
+ # Defaults to {Defaults::PARTITIONS_COUNT_CACHE_TTL_MS}.
55
+ def initialize(ttl = :not_provided, ttl_ms: :not_provided)
60
56
  @counts = {}
61
57
  @mutex_hash = {}
62
58
  # Used only for @mutex_hash access to ensure thread-safety when creating new mutexes
63
59
  @mutex_for_hash = Mutex.new
64
- @ttl = ttl
60
+
61
+ # Determine which TTL value to use
62
+ if ttl != :not_provided && ttl_ms != :not_provided
63
+ warn "DEPRECATION WARNING: Both ttl and ttl_ms were provided to PartitionsCountCache. " \
64
+ "Using ttl_ms. The ttl parameter is deprecated and will be removed in v1.0.0."
65
+ @ttl_ms = ttl_ms
66
+ elsif ttl != :not_provided
67
+ warn "DEPRECATION WARNING: ttl (seconds) parameter for PartitionsCountCache is deprecated. " \
68
+ "Use ttl_ms (milliseconds) instead. This parameter will be removed in v1.0.0."
69
+ @ttl_ms = (ttl * 1000).to_i
70
+ elsif ttl_ms == :not_provided
71
+ @ttl_ms = Defaults::PARTITIONS_COUNT_CACHE_TTL_MS
72
+ else
73
+ @ttl_ms = ttl_ms
74
+ end
65
75
  end
66
76
 
67
77
  # Reads partition count for a topic with automatic refresh when expired
@@ -137,17 +147,17 @@ module Rdkafka
137
147
 
138
148
  if current_info.nil?
139
149
  # Create new entry
140
- @counts[topic] = [monotonic_now, new_count]
150
+ @counts[topic] = [monotonic_now_ms, new_count]
141
151
  else
142
152
  current_count = current_info[1]
143
153
 
144
154
  if new_count > current_count
145
155
  # Update to higher count value
146
- current_info[0] = monotonic_now
156
+ current_info[0] = monotonic_now_ms
147
157
  current_info[1] = new_count
148
158
  else
149
159
  # Same or lower count, update timestamp only
150
- current_info[0] = monotonic_now
160
+ current_info[0] = monotonic_now_ms
151
161
  end
152
162
  end
153
163
  end
@@ -201,15 +211,15 @@ module Rdkafka
201
211
  return unless current_info
202
212
 
203
213
  # Update the timestamp in-place
204
- current_info[0] = monotonic_now
214
+ current_info[0] = monotonic_now_ms
205
215
  end
206
216
 
207
217
  # Check if a timestamp has expired based on the TTL
208
218
  #
209
- # @param timestamp [Float] Monotonic timestamp to check
219
+ # @param timestamp [Integer] Monotonic timestamp in milliseconds to check
210
220
  # @return [Boolean] true if expired, false otherwise
211
221
  def expired?(timestamp)
212
- monotonic_now - timestamp > @ttl
222
+ monotonic_now_ms - timestamp > @ttl_ms
213
223
  end
214
224
  end
215
225
  end
@@ -6,9 +6,6 @@ module Rdkafka
6
6
  include Helpers::Time
7
7
  include Helpers::OAuth
8
8
 
9
- # Empty hash used as a default
10
- EMPTY_HASH = {}.freeze
11
-
12
9
  # @private
13
10
  @@partitions_count_cache = PartitionsCountCache.new
14
11
 
@@ -17,10 +14,9 @@ module Rdkafka
17
14
  # then. Since the partitions count can only grow and should be same for all consumers and
18
15
  # producers, we can use a global cache as long as we ensure that updates only move up.
19
16
  #
17
+ # @return [Rdkafka::Producer::PartitionsCountCache]
20
18
  # @note It is critical to remember, that not all users may have statistics callbacks enabled,
21
19
  # hence we should not make assumption that this cache is always updated from the stats.
22
- #
23
- # @return [Rdkafka::Producer::PartitionsCountCache]
24
20
  def self.partitions_count_cache
25
21
  @@partitions_count_cache
26
22
  end
@@ -30,6 +26,9 @@ module Rdkafka
30
26
  @@partitions_count_cache = partitions_count_cache
31
27
  end
32
28
 
29
+ # Empty hash used as a default
30
+ EMPTY_HASH = {}.freeze
31
+
33
32
  private_constant :EMPTY_HASH
34
33
 
35
34
  # Raised when there was a critical issue when invoking rd_kafka_topic_new
@@ -64,12 +63,13 @@ module Rdkafka
64
63
  end
65
64
 
66
65
  # 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
66
+ #
69
67
  # @param topic [String] The topic name
70
68
  # @param config [Hash] config we want to use per topic basis
71
69
  # @param config_hash [Integer] hash of the config. We expect it here instead of computing it,
72
70
  # because it is already computed during the retrieval attempt in the `#produce` flow.
71
+ # @note It is not allowed to re-set the same topic config twice because of the underlying
72
+ # librdkafka caching
73
73
  def set_topic_config(topic, config, config_hash)
74
74
  # Ensure lock on topic reference just in case
75
75
  @native_kafka.with_inner do |inner|
@@ -80,25 +80,25 @@ module Rdkafka
80
80
 
81
81
  # If config is empty, we create an empty reference that will be used with defaults
82
82
  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
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
102
102
 
103
103
  topic_handle = Bindings.rd_kafka_topic_new(inner, topic, rd_topic_config)
104
104
 
@@ -122,11 +122,30 @@ module Rdkafka
122
122
  end
123
123
  end
124
124
 
125
+ # Enable IO event notifications for fiber scheduler integration
126
+ # When delivery confirmations arrive, librdkafka will write to your FD
127
+ #
128
+ # @param fd [Integer] file descriptor to signal (from IO.pipe or eventfd)
129
+ # @param payload [String] data to write to fd (default: "\x01")
130
+ # @return [nil]
131
+ # @raise [ClosedInnerError] when the producer is closed
132
+ def enable_queue_io_events(fd, payload = "\x01")
133
+ @native_kafka.enable_main_queue_io_events(fd, payload)
134
+ end
135
+
136
+ # Enable IO event notifications for background events
137
+ # @param fd [Integer] file descriptor to signal (from IO.pipe or eventfd)
138
+ # @param payload [String] data to write to fd (default: "\x01")
139
+ # @return [nil]
140
+ # @raise [ClosedInnerError] when the producer is closed
141
+ def enable_background_queue_io_events(fd, payload = "\x01")
142
+ @native_kafka.enable_background_queue_io_events(fd, payload)
143
+ end
144
+
125
145
  # Set a callback that will be called every time a message is successfully produced.
126
146
  # The callback is called with a {DeliveryReport} and {DeliveryHandle}
127
147
  #
128
- # @param callback [Proc, #call] The callback
129
- #
148
+ # @param callback [Proc, #call] callable object to handle delivery reports
130
149
  # @return [nil]
131
150
  def delivery_callback=(callback)
132
151
  raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call)
@@ -168,7 +187,7 @@ module Rdkafka
168
187
  # should be no other errors.
169
188
  #
170
189
  # @note For `timed_out` we do not raise an error to keep it backwards compatible
171
- def flush(timeout_ms=5_000)
190
+ def flush(timeout_ms = Defaults::PRODUCER_FLUSH_TIMEOUT_MS)
172
191
  closed_producer_check(__method__)
173
192
 
174
193
  code = nil
@@ -208,11 +227,76 @@ module Rdkafka
208
227
  code.zero? || raise(Rdkafka::RdkafkaError.new(code))
209
228
 
210
229
  # Wait for the purge to affect everything
211
- sleep(0.001) until flush(100)
230
+ sleep(Defaults::PRODUCER_PURGE_SLEEP_INTERVAL_MS / 1000.0) until flush(Defaults::PRODUCER_PURGE_FLUSH_TIMEOUT_MS)
212
231
 
213
232
  true
214
233
  end
215
234
 
235
+ # Returns the number of messages and requests waiting to be sent to the broker as well as
236
+ # delivery reports queued for the application.
237
+ #
238
+ # This provides visibility into the producer's internal queue depth, useful for:
239
+ # - Monitoring producer backpressure
240
+ # - Implementing custom flow control
241
+ # - Debugging message delivery issues
242
+ # - Graceful shutdown logic (wait until queue is empty)
243
+ #
244
+ # @return [Integer] the number of messages in the queue
245
+ # @raise [Rdkafka::ClosedProducerError] if called on a closed producer
246
+ #
247
+ # @note This method is thread-safe as it uses the @native_kafka.with_inner synchronization
248
+ #
249
+ # @example
250
+ # producer.queue_size #=> 42
251
+ def queue_size
252
+ closed_producer_check(__method__)
253
+
254
+ @native_kafka.with_inner do |inner|
255
+ Rdkafka::Bindings.rd_kafka_outq_len(inner)
256
+ end
257
+ end
258
+
259
+ alias_method :queue_length, :queue_size
260
+
261
+ # Polls for events in a non-blocking loop, yielding the count after each iteration.
262
+ #
263
+ # This method processes delivery callbacks in a single GVL/mutex session, which is more
264
+ # efficient than repeated individual polls. It uses non-blocking polls internally
265
+ # (no GVL release between polls).
266
+ #
267
+ # Yields the count of events processed after each poll iteration, allowing the caller
268
+ # to implement timeout or other termination logic by returning `:stop`.
269
+ #
270
+ # @yield [count] Called after each poll iteration
271
+ # @yieldparam count [Integer] Number of events processed in this iteration
272
+ # @yieldreturn [Symbol, Object] Return `:stop` to break the loop, any other value continues
273
+ # @return [nil]
274
+ # @raise [Rdkafka::ClosedProducerError] if called on a closed producer
275
+ #
276
+ # @note This method holds the inner lock until the queue is empty or `:stop` is returned.
277
+ # Other producer operations (produce, close, etc.) will wait until this method returns.
278
+ # @note This method is thread-safe as it uses @native_kafka.with_inner synchronization
279
+ #
280
+ # @example Drain all pending callbacks
281
+ # producer.events_poll_nb_each { |_count| }
282
+ #
283
+ # @example With timeout control
284
+ # deadline = monotonic_now + timeout_ms
285
+ # producer.events_poll_nb_each do |_count|
286
+ # :stop if monotonic_now >= deadline
287
+ # end
288
+ def events_poll_nb_each
289
+ closed_producer_check(__method__)
290
+
291
+ @native_kafka.with_inner do |inner|
292
+ loop do
293
+ count = Rdkafka::Bindings.rd_kafka_poll_nb(inner, 0)
294
+ break if count.zero?
295
+ break if yield(count) == :stop
296
+ end
297
+ end
298
+ end
299
+
216
300
  # Partition count for a given topic.
217
301
  #
218
302
  # @param topic [String] The topic name.
@@ -237,13 +321,13 @@ module Rdkafka
237
321
  topic_metadata = ::Rdkafka::Metadata.new(inner, topic).topics&.first
238
322
  end
239
323
 
240
- topic_metadata ? topic_metadata[:partition_count] : -1
324
+ topic_metadata ? topic_metadata[:partition_count] : Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
241
325
  end
242
326
  rescue Rdkafka::RdkafkaError => e
243
327
  # 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
328
+ # raised. We here return RD_KAFKA_PARTITION_UA so this can happen without early error
329
+ # happening on metadata discovery.
330
+ return Rdkafka::Bindings::RD_KAFKA_PARTITION_UA if e.code == :unknown_topic_or_part
247
331
 
248
332
  raise(e)
249
333
  end
@@ -254,14 +338,15 @@ module Rdkafka
254
338
  # When a timestamp is provided this is used instead of the auto-generated timestamp.
255
339
  #
256
340
  # @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
341
+ # @param payload [String, nil]
342
+ # @param key [String, nil]
343
+ # @param partition [Integer, nil] Optional partition to produce to
260
344
  # @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
345
+ # @param timestamp [Time, Integer, nil] Optional timestamp of this message. Integer timestamp is in milliseconds since Jan 1 1970.
346
+ # @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
347
  # @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
348
  # @param topic_config [Hash] topic config for given message dispatch. Allows to send messages to topics with different configuration
349
+ # @param partitioner [String] name of the partitioner to use
265
350
  #
266
351
  # @return [DeliveryHandle] Delivery handle that can be used to wait for the result of producing this message
267
352
  #
@@ -284,17 +369,17 @@ module Rdkafka
284
369
 
285
370
  # Get payload length
286
371
  payload_size = if payload.nil?
287
- 0
288
- else
289
- payload.bytesize
290
- end
372
+ 0
373
+ else
374
+ payload.bytesize
375
+ end
291
376
 
292
377
  # Get key length
293
378
  key_size = if key.nil?
294
- 0
295
- else
296
- key.bytesize
297
- end
379
+ 0
380
+ else
381
+ key.bytesize
382
+ end
298
383
 
299
384
  topic_config_hash = topic_config.hash
300
385
 
@@ -311,36 +396,39 @@ module Rdkafka
311
396
  selected_partitioner = @topics_configs.dig(topic, topic_config_hash, :partitioner) || partitioner
312
397
 
313
398
  # 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?
399
+ if partition_count.positive?
400
+ partition = Rdkafka::Bindings.partitioner(
401
+ topic_ref,
402
+ partition_key,
403
+ partition_count,
404
+ selected_partitioner
405
+ )
406
+ end
319
407
  end
320
408
 
321
- # If partition is nil, use -1 to let librdafka set the partition randomly or
409
+ # If partition is nil, use RD_KAFKA_PARTITION_UA to let librdafka set the partition randomly or
322
410
  # based on the key when present.
323
- partition ||= -1
411
+ partition ||= Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
324
412
 
325
413
  # If timestamp is nil use 0 and let Kafka set one. If an integer or time
326
414
  # use it.
327
415
  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
416
+ 0
417
+ elsif timestamp.is_a?(Integer)
418
+ timestamp
419
+ elsif timestamp.is_a?(Time)
420
+ (timestamp.to_i * 1000) + (timestamp.usec / 1000)
421
+ else
422
+ raise TypeError.new("Timestamp has to be nil, an Integer or a Time")
423
+ end
336
424
 
337
425
  delivery_handle = DeliveryHandle.new
338
426
  delivery_handle.label = label
339
427
  delivery_handle.topic = topic
340
428
  delivery_handle[:pending] = true
341
- delivery_handle[:response] = -1
342
- delivery_handle[:partition] = -1
343
- delivery_handle[:offset] = -1
429
+ delivery_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
430
+ delivery_handle[:partition] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
431
+ delivery_handle[:offset] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
344
432
  DeliveryHandle.register(delivery_handle)
345
433
 
346
434
  args = [
@@ -350,29 +438,27 @@ module Rdkafka
350
438
  :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_KEY, :buffer_in, key, :size_t, key_size,
351
439
  :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_PARTITION, :int32, partition,
352
440
  :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_TIMESTAMP, :int64, raw_timestamp,
353
- :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_OPAQUE, :pointer, delivery_handle,
441
+ :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_OPAQUE, :pointer, delivery_handle
354
442
  ]
355
443
 
356
- if headers
357
- headers.each do |key0, value0|
358
- key = key0.to_s
359
- if value0.is_a?(Array)
360
- # Handle array of values per KIP-82
361
- value0.each do |value|
362
- value = value.to_s
363
- args << :int << Rdkafka::Bindings::RD_KAFKA_VTYPE_HEADER
364
- args << :string << key
365
- args << :pointer << value
366
- args << :size_t << value.bytesize
367
- end
368
- else
369
- # Handle single value
370
- value = value0.to_s
444
+ headers&.each do |key0, value0|
445
+ key = key0.to_s
446
+ if value0.is_a?(Array)
447
+ # Handle array of values per KIP-82
448
+ value0.each do |value|
449
+ value = value.to_s
371
450
  args << :int << Rdkafka::Bindings::RD_KAFKA_VTYPE_HEADER
372
451
  args << :string << key
373
452
  args << :pointer << value
374
453
  args << :size_t << value.bytesize
375
454
  end
455
+ else
456
+ # Handle single value
457
+ value = value0.to_s
458
+ args << :int << Rdkafka::Bindings::RD_KAFKA_VTYPE_HEADER
459
+ args << :string << key
460
+ args << :pointer << value
461
+ args << :size_t << value.bytesize
376
462
  end
377
463
  end
378
464
 
@@ -387,7 +473,7 @@ module Rdkafka
387
473
  end
388
474
 
389
475
  # Raise error if the produce call was not successful
390
- if response != 0
476
+ if response != Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
391
477
  DeliveryHandle.remove(delivery_handle.to_ptr.address)
392
478
  raise RdkafkaError.new(response)
393
479
  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.27.0"
6
+ # Target librdkafka version to be used
7
+ LIBRDKAFKA_VERSION = "2.14.0"
8
+ # SHA256 hash of the librdkafka source tarball for verification
9
+ LIBRDKAFKA_SOURCE_SHA256 = "c05c03ef00a13a8463fac3e8918c04843c416f11ced58c889d806a88ca92cf99"
7
10
  end
data/lib/rdkafka.rb CHANGED
@@ -8,6 +8,7 @@ require "json"
8
8
  require "rdkafka/version"
9
9
  require "rdkafka/helpers/time"
10
10
  require "rdkafka/helpers/oauth"
11
+ require "rdkafka/defaults"
11
12
  require "rdkafka/abstract_handle"
12
13
  require "rdkafka/admin"
13
14
  require "rdkafka/admin/create_topic_handle"
@@ -28,6 +29,8 @@ require "rdkafka/admin/describe_configs_handle"
28
29
  require "rdkafka/admin/describe_configs_report"
29
30
  require "rdkafka/admin/incremental_alter_configs_handle"
30
31
  require "rdkafka/admin/incremental_alter_configs_report"
32
+ require "rdkafka/admin/list_offsets_handle"
33
+ require "rdkafka/admin/list_offsets_report"
31
34
  require "rdkafka/admin/acl_binding_result"
32
35
  require "rdkafka/admin/config_binding_result"
33
36
  require "rdkafka/admin/config_resource_binding_result"