rdkafka 0.25.0-aarch64-linux-gnu → 0.26.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile +5 -6
  4. data/Gemfile.lint +14 -0
  5. data/Gemfile.lint.lock +123 -0
  6. data/README.md +2 -1
  7. data/Rakefile +21 -21
  8. data/bin/verify_kafka_warnings +2 -0
  9. data/docker-compose-ssl.yml +2 -2
  10. data/docker-compose.yml +2 -2
  11. data/ext/librdkafka.so +0 -0
  12. data/lib/rdkafka/admin/acl_binding_result.rb +4 -4
  13. data/lib/rdkafka/admin/create_acl_handle.rb +4 -4
  14. data/lib/rdkafka/admin/create_acl_report.rb +0 -2
  15. data/lib/rdkafka/admin/create_partitions_handle.rb +5 -5
  16. data/lib/rdkafka/admin/create_topic_handle.rb +5 -5
  17. data/lib/rdkafka/admin/delete_acl_handle.rb +6 -6
  18. data/lib/rdkafka/admin/delete_acl_report.rb +2 -3
  19. data/lib/rdkafka/admin/delete_groups_handle.rb +5 -5
  20. data/lib/rdkafka/admin/delete_topic_handle.rb +5 -5
  21. data/lib/rdkafka/admin/describe_acl_handle.rb +6 -6
  22. data/lib/rdkafka/admin/describe_acl_report.rb +2 -3
  23. data/lib/rdkafka/admin/describe_configs_handle.rb +4 -4
  24. data/lib/rdkafka/admin/describe_configs_report.rb +1 -1
  25. data/lib/rdkafka/admin/incremental_alter_configs_handle.rb +4 -4
  26. data/lib/rdkafka/admin/incremental_alter_configs_report.rb +1 -1
  27. data/lib/rdkafka/admin/list_offsets_handle.rb +36 -0
  28. data/lib/rdkafka/admin/list_offsets_report.rb +51 -0
  29. data/lib/rdkafka/admin.rb +189 -24
  30. data/lib/rdkafka/bindings.rb +121 -84
  31. data/lib/rdkafka/callbacks.rb +53 -10
  32. data/lib/rdkafka/config.rb +20 -20
  33. data/lib/rdkafka/consumer/message.rb +5 -8
  34. data/lib/rdkafka/consumer/partition.rb +2 -2
  35. data/lib/rdkafka/consumer/topic_partition_list.rb +10 -10
  36. data/lib/rdkafka/consumer.rb +208 -18
  37. data/lib/rdkafka/error.rb +25 -14
  38. data/lib/rdkafka/helpers/oauth.rb +0 -1
  39. data/lib/rdkafka/helpers/time.rb +5 -0
  40. data/lib/rdkafka/metadata.rb +16 -16
  41. data/lib/rdkafka/native_kafka.rb +63 -2
  42. data/lib/rdkafka/producer/delivery_handle.rb +5 -5
  43. data/lib/rdkafka/producer/delivery_report.rb +1 -1
  44. data/lib/rdkafka/producer/partitions_count_cache.rb +6 -6
  45. data/lib/rdkafka/producer.rb +117 -57
  46. data/lib/rdkafka/version.rb +3 -3
  47. data/lib/rdkafka.rb +2 -0
  48. data/package-lock.json +331 -0
  49. data/package.json +9 -0
  50. data/rdkafka.gemspec +39 -40
  51. data/renovate.json +21 -0
  52. metadata +8 -2
@@ -17,10 +17,10 @@ module Rdkafka
17
17
  # Returns the library extension based on the host OS
18
18
  # @return [String] 'dylib' on macOS, 'so' on other systems
19
19
  def self.lib_extension
20
- if RbConfig::CONFIG['host_os'] =~ /darwin/
21
- 'dylib'
20
+ if /darwin/.match?(RbConfig::CONFIG["host_os"])
21
+ "dylib"
22
22
  else
23
- 'so'
23
+ "so"
24
24
  end
25
25
  end
26
26
 
@@ -31,8 +31,8 @@ module Rdkafka
31
31
  error_message = e.message
32
32
 
33
33
  # Check if this is a glibc version mismatch error
34
- if error_message =~ /GLIBC_[\d.]+['"` ]?\s*not found/i
35
- glibc_version = error_message[/GLIBC_([\d.]+)/, 1] || 'unknown'
34
+ if /GLIBC_[\d.]+['"` ]?\s*not found/i.match?(error_message)
35
+ glibc_version = error_message[/GLIBC_([\d.]+)/, 1] || "unknown"
36
36
 
37
37
  raise Rdkafka::LibraryLoadError, <<~ERROR_MSG.strip
38
38
  Failed to load librdkafka due to glibc compatibility issue.
@@ -64,12 +64,12 @@ module Rdkafka
64
64
  RD_KAFKA_RESP_ERR__NOENT = -156
65
65
  RD_KAFKA_RESP_ERR_NO_ERROR = 0
66
66
 
67
- RD_KAFKA_OFFSET_END = -1
67
+ RD_KAFKA_OFFSET_END = -1
68
68
  RD_KAFKA_OFFSET_BEGINNING = -2
69
- RD_KAFKA_OFFSET_STORED = -1000
70
- RD_KAFKA_OFFSET_INVALID = -1001
69
+ RD_KAFKA_OFFSET_STORED = -1000
70
+ RD_KAFKA_OFFSET_INVALID = -1001
71
71
 
72
- RD_KAFKA_PARTITION_UA = -1
72
+ RD_KAFKA_PARTITION_UA = -1
73
73
  RD_KAFKA_PARTITION_UA_STR = RD_KAFKA_PARTITION_UA.to_s.freeze
74
74
 
75
75
  EMPTY_HASH = {}.freeze
@@ -90,6 +90,12 @@ module Rdkafka
90
90
  attach_function :rd_kafka_poll, [:pointer, :int], :int, blocking: true
91
91
  attach_function :rd_kafka_outq_len, [:pointer], :int, blocking: true
92
92
 
93
+ # Non-blocking poll variants (do not release GVL)
94
+ # These are more efficient for poll(0) calls in fiber schedulers where GVL
95
+ # release/reacquire overhead is wasteful since we don't expect to wait.
96
+ # Uses the same underlying C function but with blocking: false to skip GVL release.
97
+ attach_function :rd_kafka_poll_nb, :rd_kafka_poll, [:pointer, :int], :int, blocking: false
98
+
93
99
  # Metadata
94
100
 
95
101
  attach_function :rd_kafka_name, [:pointer], :string
@@ -101,14 +107,14 @@ module Rdkafka
101
107
  # FFI struct representing a Kafka message (rd_kafka_message_t)
102
108
  class Message < FFI::Struct
103
109
  layout :err, :int,
104
- :rkt, :pointer,
105
- :partition, :int32,
106
- :payload, :pointer,
107
- :len, :size_t,
108
- :key, :pointer,
109
- :key_len, :size_t,
110
- :offset, :int64,
111
- :_private, :pointer
110
+ :rkt, :pointer,
111
+ :partition, :int32,
112
+ :payload, :pointer,
113
+ :len, :size_t,
114
+ :key, :pointer,
115
+ :key_len, :size_t,
116
+ :offset, :int64,
117
+ :_private, :pointer
112
118
  end
113
119
 
114
120
  attach_function :rd_kafka_message_destroy, [:pointer], :void
@@ -120,20 +126,20 @@ module Rdkafka
120
126
  # FFI struct representing a topic partition (rd_kafka_topic_partition_t)
121
127
  class TopicPartition < FFI::Struct
122
128
  layout :topic, :string,
123
- :partition, :int32,
124
- :offset, :int64,
125
- :metadata, :pointer,
126
- :metadata_size, :size_t,
127
- :opaque, :pointer,
128
- :err, :int,
129
- :_private, :pointer
129
+ :partition, :int32,
130
+ :offset, :int64,
131
+ :metadata, :pointer,
132
+ :metadata_size, :size_t,
133
+ :opaque, :pointer,
134
+ :err, :int,
135
+ :_private, :pointer
130
136
  end
131
137
 
132
138
  # FFI struct representing a topic partition list (rd_kafka_topic_partition_list_t)
133
139
  class TopicPartitionList < FFI::Struct
134
140
  layout :cnt, :int,
135
- :size, :int,
136
- :elems, :pointer
141
+ :size, :int,
142
+ :elems, :pointer
137
143
  end
138
144
 
139
145
  attach_function :rd_kafka_topic_partition_list_new, [:int32], :pointer
@@ -148,7 +154,7 @@ module Rdkafka
148
154
  # separate errors results if obtaining configuration was not possible for any reason
149
155
  class ConfigResource < FFI::Struct
150
156
  layout :type, :int,
151
- :name, :string
157
+ :name, :string
152
158
  end
153
159
 
154
160
  attach_function :rd_kafka_DescribeConfigs, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
@@ -177,16 +183,37 @@ module Rdkafka
177
183
  RD_KAFKA_ADMIN_OP_INCREMENTALALTERCONFIGS = 16
178
184
  RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT = 131072
179
185
 
180
- RD_KAFKA_ALTER_CONFIG_OP_TYPE_SET = 0
181
- RD_KAFKA_ALTER_CONFIG_OP_TYPE_DELETE = 1
182
- RD_KAFKA_ALTER_CONFIG_OP_TYPE_APPEND = 2
186
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_SET = 0
187
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_DELETE = 1
188
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_APPEND = 2
183
189
  RD_KAFKA_ALTER_CONFIG_OP_TYPE_SUBTRACT = 3
184
190
 
191
+ # List Offsets
192
+ RD_KAFKA_ADMIN_OP_LISTOFFSETS = 20
193
+ RD_KAFKA_EVENT_LISTOFFSETS_RESULT = 0x400000
194
+
195
+ # rd_kafka_IsolationLevel_t
196
+ RD_KAFKA_ISOLATION_LEVEL_READ_UNCOMMITTED = 0
197
+ RD_KAFKA_ISOLATION_LEVEL_READ_COMMITTED = 1
198
+
199
+ # rd_kafka_OffsetSpec_t
200
+ RD_KAFKA_OFFSET_SPEC_MAX_TIMESTAMP = -3
201
+ RD_KAFKA_OFFSET_SPEC_EARLIEST = -2
202
+ RD_KAFKA_OFFSET_SPEC_LATEST = -1
203
+
204
+ attach_function :rd_kafka_ListOffsets, [:pointer, :pointer, :pointer, :pointer], :void, blocking: true
205
+ attach_function :rd_kafka_event_ListOffsets_result, [:pointer], :pointer
206
+ attach_function :rd_kafka_ListOffsets_result_infos, [:pointer, :pointer], :pointer
207
+ attach_function :rd_kafka_ListOffsetsResultInfo_topic_partition, [:pointer], :pointer
208
+ attach_function :rd_kafka_ListOffsetsResultInfo_timestamp, [:pointer], :int64
209
+ attach_function :rd_kafka_AdminOptions_set_isolation_level, [:pointer, :int], :pointer
210
+ attach_function :rd_kafka_topic_partition_get_leader_epoch, [:pointer], :int32
211
+
185
212
  # FFI struct for error description (rd_kafka_err_desc)
186
213
  class NativeErrorDesc < FFI::Struct
187
214
  layout :code, :int,
188
- :name, :pointer,
189
- :desc, :pointer
215
+ :name, :pointer,
216
+ :desc, :pointer
190
217
  end
191
218
 
192
219
  attach_function :rd_kafka_err2name, [:int], :string
@@ -222,6 +249,15 @@ module Rdkafka
222
249
  # Log queue
223
250
  attach_function :rd_kafka_set_log_queue, [:pointer, :pointer], :void
224
251
  attach_function :rd_kafka_queue_get_main, [:pointer], :pointer
252
+ attach_function :rd_kafka_queue_get_background, [:pointer], :pointer
253
+
254
+ # Queue IO Event Support - for fiber scheduler integration
255
+ # Enables notifications to a custom FD when queue transitions from empty to non-empty
256
+ # @param queue rd_kafka_queue_t* - the queue to monitor
257
+ # @param fd int - file descriptor to write to (provide your own pipe/eventfd)
258
+ # @param payload const void* - data to write to fd
259
+ # @param size size_t - size of payload
260
+ attach_function :rd_kafka_queue_io_event_enable, [:pointer, :int, :pointer, :size_t], :void
225
261
  # Per topic configs
226
262
  attach_function :rd_kafka_topic_conf_new, [], :pointer
227
263
  attach_function :rd_kafka_topic_conf_set, [:pointer, :string, :string, :pointer, :int], :kafka_config_response
@@ -230,19 +266,19 @@ module Rdkafka
230
266
  :void, [:pointer, :int, :string, :string]
231
267
  ) do |_client_ptr, level, _level_string, line|
232
268
  severity = case level
233
- when 0, 1, 2
234
- Logger::FATAL
235
- when 3
236
- Logger::ERROR
237
- when 4
238
- Logger::WARN
239
- when 5, 6
240
- Logger::INFO
241
- when 7
242
- Logger::DEBUG
243
- else
244
- Logger::UNKNOWN
245
- end
269
+ when 0, 1, 2
270
+ Logger::FATAL
271
+ when 3
272
+ Logger::ERROR
273
+ when 4
274
+ Logger::WARN
275
+ when 5, 6
276
+ Logger::INFO
277
+ when 7
278
+ Logger::DEBUG
279
+ else
280
+ Logger::UNKNOWN
281
+ end
246
282
 
247
283
  Rdkafka::Config.ensure_log_thread
248
284
  Rdkafka::Config.log_queue << [severity, "rdkafka: #{line}"]
@@ -268,8 +304,8 @@ module Rdkafka
268
304
  #
269
305
  # Since this cache is shared, having few consumers and/or producers in one process will
270
306
  # automatically improve the querying times even with low refresh times.
271
- (stats['topics'] || EMPTY_HASH).each do |topic_name, details|
272
- partitions_count = details['partitions'].keys.reject { |k| k == RD_KAFKA_PARTITION_UA_STR }.size
307
+ (stats["topics"] || EMPTY_HASH).each do |topic_name, details|
308
+ partitions_count = details["partitions"].keys.count { |k| !(k == RD_KAFKA_PARTITION_UA_STR) }
273
309
 
274
310
  next unless partitions_count.positive?
275
311
 
@@ -285,9 +321,10 @@ module Rdkafka
285
321
 
286
322
  ErrorCallback = FFI::Function.new(
287
323
  :void, [:pointer, :int, :string, :pointer]
288
- ) do |_client_prr, err_code, reason, _opaque|
324
+ ) do |client_ptr, err_code, reason, _opaque|
289
325
  if Rdkafka::Config.error_callback
290
- error = Rdkafka::RdkafkaError.new(err_code, broker_message: reason)
326
+ instance_name = client_ptr.null? ? nil : Rdkafka::Bindings.rd_kafka_name(client_ptr)
327
+ error = Rdkafka::RdkafkaError.new(err_code, broker_message: reason, instance_name: instance_name)
291
328
  error.set_backtrace(caller)
292
329
  Rdkafka::Config.error_callback.call(error)
293
330
  end
@@ -314,9 +351,7 @@ module Rdkafka
314
351
  OAuthbearerTokenRefreshCallback = FFI::Function.new(
315
352
  :void, [:pointer, :string, :pointer]
316
353
  ) do |client_ptr, config, _opaque|
317
- if Rdkafka::Config.oauthbearer_token_refresh_callback
318
- Rdkafka::Config.oauthbearer_token_refresh_callback.call(config, Rdkafka::Bindings.rd_kafka_name(client_ptr))
319
- end
354
+ Rdkafka::Config.oauthbearer_token_refresh_callback&.call(config, Rdkafka::Bindings.rd_kafka_name(client_ptr))
320
355
  end
321
356
 
322
357
  # Handle
@@ -344,6 +379,9 @@ module Rdkafka
344
379
  attach_function :rd_kafka_commit, [:pointer, :pointer, :bool], :int, blocking: true
345
380
  attach_function :rd_kafka_poll_set_consumer, [:pointer], :void, blocking: true
346
381
  attach_function :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: true
382
+ # Non-blocking consumer poll variant (does not release GVL)
383
+ # More efficient for poll(0) calls in fiber schedulers.
384
+ attach_function :rd_kafka_consumer_poll_nb, :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: false
347
385
  attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
348
386
  attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
349
387
  attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
@@ -426,8 +464,8 @@ module Rdkafka
426
464
 
427
465
  # Hash mapping partitioner names to their FFI function symbols
428
466
  # @return [Hash{String => Symbol}]
429
- PARTITIONERS = %w(random consistent consistent_random murmur2 murmur2_random fnv1a fnv1a_random).each_with_object({}) do |name, hsh|
430
- method_name = "rd_kafka_msg_partitioner_#{name}".to_sym
467
+ PARTITIONERS = %w[random consistent consistent_random murmur2 murmur2_random fnv1a fnv1a_random].each_with_object({}) do |name, hsh|
468
+ method_name = :"rd_kafka_msg_partitioner_#{name}"
431
469
  attach_function method_name, [:pointer, :pointer, :size_t, :int32, :pointer, :pointer], :int32
432
470
  hsh[name] = method_name
433
471
  end
@@ -453,7 +491,7 @@ module Rdkafka
453
491
  end
454
492
 
455
493
  # Create Topics
456
- RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
494
+ RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
457
495
  RD_KAFKA_EVENT_CREATETOPICS_RESULT = 100 # rd_kafka_event_type_t
458
496
 
459
497
  attach_function :rd_kafka_CreateTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
@@ -464,7 +502,7 @@ module Rdkafka
464
502
  attach_function :rd_kafka_CreateTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
465
503
 
466
504
  # Delete Topics
467
- RD_KAFKA_ADMIN_OP_DELETETOPICS = 2 # rd_kafka_admin_op_t
505
+ RD_KAFKA_ADMIN_OP_DELETETOPICS = 2 # rd_kafka_admin_op_t
468
506
  RD_KAFKA_EVENT_DELETETOPICS_RESULT = 101 # rd_kafka_event_type_t
469
507
 
470
508
  attach_function :rd_kafka_DeleteTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :int32, blocking: true
@@ -495,7 +533,6 @@ module Rdkafka
495
533
 
496
534
  # Background Queue and Callback
497
535
 
498
- attach_function :rd_kafka_queue_get_background, [:pointer], :pointer
499
536
  attach_function :rd_kafka_conf_set_background_event_cb, [:pointer, :pointer], :void
500
537
  attach_function :rd_kafka_queue_destroy, [:pointer], :void
501
538
 
@@ -517,7 +554,7 @@ module Rdkafka
517
554
  attach_function :rd_kafka_topic_result_name, [:pointer], :pointer
518
555
 
519
556
  # Create Acls
520
- RD_KAFKA_ADMIN_OP_CREATEACLS = 9
557
+ RD_KAFKA_ADMIN_OP_CREATEACLS = 9
521
558
  RD_KAFKA_EVENT_CREATEACLS_RESULT = 1024
522
559
 
523
560
  attach_function :rd_kafka_CreateAcls, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
@@ -525,7 +562,7 @@ module Rdkafka
525
562
  attach_function :rd_kafka_CreateAcls_result_acls, [:pointer, :pointer], :pointer
526
563
 
527
564
  # Delete Acls
528
- RD_KAFKA_ADMIN_OP_DELETEACLS = 11
565
+ RD_KAFKA_ADMIN_OP_DELETEACLS = 11
529
566
  RD_KAFKA_EVENT_DELETEACLS_RESULT = 4096
530
567
 
531
568
  attach_function :rd_kafka_DeleteAcls, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
@@ -535,7 +572,7 @@ module Rdkafka
535
572
  attach_function :rd_kafka_DeleteAcls_result_response_matching_acls, [:pointer, :pointer], :pointer
536
573
 
537
574
  # Describe Acls
538
- RD_KAFKA_ADMIN_OP_DESCRIBEACLS = 10
575
+ RD_KAFKA_ADMIN_OP_DESCRIBEACLS = 10
539
576
  RD_KAFKA_EVENT_DESCRIBEACLS_RESULT = 2048
540
577
 
541
578
  attach_function :rd_kafka_DescribeAcls, [:pointer, :pointer, :pointer, :pointer], :void
@@ -551,41 +588,42 @@ module Rdkafka
551
588
  attach_function :rd_kafka_AclBinding_host, [:pointer], :pointer
552
589
  attach_function :rd_kafka_AclBinding_operation, [:pointer], :int32
553
590
  attach_function :rd_kafka_AclBinding_permission_type, [:pointer], :int32
554
- attach_function :rd_kafka_AclBinding_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t ], :pointer
555
- attach_function :rd_kafka_AclBindingFilter_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t ], :pointer
591
+ attach_function :rd_kafka_AclBinding_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t], :pointer
592
+ attach_function :rd_kafka_AclBindingFilter_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t], :pointer
556
593
  attach_function :rd_kafka_AclBinding_destroy, [:pointer], :void
557
594
 
558
595
  # rd_kafka_ResourceType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
559
- RD_KAFKA_RESOURCE_ANY = 1
596
+ RD_KAFKA_RESOURCE_ANY = 1
560
597
  RD_KAFKA_RESOURCE_TOPIC = 2
561
598
  RD_KAFKA_RESOURCE_GROUP = 3
562
599
  RD_KAFKA_RESOURCE_BROKER = 4
563
600
  RD_KAFKA_RESOURCE_TRANSACTIONAL_ID = 5
564
601
 
565
602
  # rd_kafka_ResourcePatternType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
566
- RD_KAFKA_RESOURCE_PATTERN_ANY = 1
567
- RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
568
- RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
603
+ RD_KAFKA_RESOURCE_PATTERN_UNKNOWN = 0
604
+ RD_KAFKA_RESOURCE_PATTERN_ANY = 1
605
+ RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
606
+ RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
569
607
  RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
570
608
 
571
609
  # rd_kafka_AclOperation_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
572
- RD_KAFKA_ACL_OPERATION_ANY = 1
573
- RD_KAFKA_ACL_OPERATION_ALL = 2
574
- RD_KAFKA_ACL_OPERATION_READ = 3
575
- RD_KAFKA_ACL_OPERATION_WRITE = 4
576
- RD_KAFKA_ACL_OPERATION_CREATE = 5
577
- RD_KAFKA_ACL_OPERATION_DELETE = 6
578
- RD_KAFKA_ACL_OPERATION_ALTER = 7
579
- RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
580
- RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
610
+ RD_KAFKA_ACL_OPERATION_ANY = 1
611
+ RD_KAFKA_ACL_OPERATION_ALL = 2
612
+ RD_KAFKA_ACL_OPERATION_READ = 3
613
+ RD_KAFKA_ACL_OPERATION_WRITE = 4
614
+ RD_KAFKA_ACL_OPERATION_CREATE = 5
615
+ RD_KAFKA_ACL_OPERATION_DELETE = 6
616
+ RD_KAFKA_ACL_OPERATION_ALTER = 7
617
+ RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
618
+ RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
581
619
  RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
582
- RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
620
+ RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
583
621
  RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
584
622
 
585
623
  # rd_kafka_AclPermissionType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
586
- RD_KAFKA_ACL_PERMISSION_TYPE_ANY = 1
587
- RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
588
- RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
624
+ RD_KAFKA_ACL_PERMISSION_TYPE_ANY = 1
625
+ RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
626
+ RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
589
627
 
590
628
  # Extracting error details from Acl results
591
629
  attach_function :rd_kafka_acl_result_error, [:pointer], :pointer
@@ -595,14 +633,13 @@ module Rdkafka
595
633
  attach_function :rd_kafka_event_error_string, [:pointer], :pointer
596
634
  attach_function :rd_kafka_AclBinding_error, [:pointer], :pointer
597
635
 
598
-
599
636
  # FFI struct for native error (rd_kafka_error_t)
600
637
  class NativeError < FFI::Struct
601
638
  layout :code, :int32,
602
- :errstr, :pointer,
603
- :fatal, :u_int8_t,
604
- :retriable, :u_int8_t,
605
- :txn_requires_abort, :u_int8_t
639
+ :errstr, :pointer,
640
+ :fatal, :u_int8_t,
641
+ :retriable, :u_int8_t,
642
+ :txn_requires_abort, :u_int8_t
606
643
  end
607
644
 
608
645
  attach_function :rd_kafka_group_result_error, [:pointer], NativeError.by_ref # rd_kafka_group_result_t* => rd_kafka_error_t*
@@ -92,15 +92,15 @@ module Rdkafka
92
92
 
93
93
  # @param acl_result_pointer [FFI::Pointer] pointer to the delete ACL result response struct
94
94
  def initialize(acl_result_pointer)
95
- @matching_acls=[]
95
+ @matching_acls = []
96
96
  rd_kafka_error_pointer = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_response_error(acl_result_pointer)
97
97
  @result_error = Rdkafka::Bindings.rd_kafka_error_code(rd_kafka_error_pointer)
98
98
  @error_string = Rdkafka::Bindings.rd_kafka_error_string(rd_kafka_error_pointer)
99
99
  if @result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
100
- # Get the number of matching acls
101
- pointer_to_size_t = FFI::MemoryPointer.new(:int32)
102
- @matching_acls = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_response_matching_acls(acl_result_pointer, pointer_to_size_t)
103
- @matching_acls_count = pointer_to_size_t.read_int
100
+ # Get the number of matching acls
101
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
102
+ @matching_acls = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_response_matching_acls(acl_result_pointer, pointer_to_size_t)
103
+ @matching_acls_count = pointer_to_size_t.read_int
104
104
  end
105
105
  end
106
106
 
@@ -123,7 +123,7 @@ module Rdkafka
123
123
 
124
124
  # @param event_ptr [FFI::Pointer] pointer to the event
125
125
  def initialize(event_ptr)
126
- @matching_acls=[]
126
+ @matching_acls = []
127
127
  @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
128
128
  @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
129
129
  if @result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
@@ -144,7 +144,7 @@ module Rdkafka
144
144
 
145
145
  # @param event_ptr [FFI::Pointer] pointer to the event
146
146
  def initialize(event_ptr)
147
- @results=[]
147
+ @results = []
148
148
  @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
149
149
  @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
150
150
 
@@ -166,7 +166,7 @@ module Rdkafka
166
166
 
167
167
  # @param event_ptr [FFI::Pointer] pointer to the event
168
168
  def initialize(event_ptr)
169
- @results=[]
169
+ @results = []
170
170
  @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
171
171
  @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
172
172
 
@@ -180,6 +180,27 @@ module Rdkafka
180
180
  end
181
181
  end
182
182
 
183
+ # Extracts attributes of rd_kafka_ListOffsets_result_t
184
+ #
185
+ # @private
186
+ class ListOffsetsResult
187
+ attr_reader :result_error, :error_string, :result_infos, :result_count
188
+
189
+ # @param event_ptr [FFI::Pointer] pointer to the event
190
+ def initialize(event_ptr)
191
+ @result_infos = FFI::Pointer::NULL
192
+ @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
193
+ @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
194
+
195
+ if @result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
196
+ list_offsets_result = Rdkafka::Bindings.rd_kafka_event_ListOffsets_result(event_ptr)
197
+ pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
198
+ @result_infos = Rdkafka::Bindings.rd_kafka_ListOffsets_result_infos(list_offsets_result, pointer_to_size_t)
199
+ @result_count = pointer_to_size_t.read(:size_t)
200
+ end
201
+ end
202
+ end
203
+
183
204
  # @private
184
205
  class BackgroundEventCallback
185
206
  # Handles background events from librdkafka
@@ -206,6 +227,8 @@ module Rdkafka
206
227
  process_describe_acl(event_ptr)
207
228
  when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT
208
229
  process_delete_groups(event_ptr)
230
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTOFFSETS_RESULT
231
+ process_list_offsets(event_ptr)
209
232
  end
210
233
  end
211
234
 
@@ -392,6 +415,26 @@ module Rdkafka
392
415
  describe_acl_handle.unlock
393
416
  end
394
417
  end
418
+
419
+ # Processes list offsets result event
420
+ # @param event_ptr [FFI::Pointer] pointer to the event
421
+ def self.process_list_offsets(event_ptr)
422
+ list_offsets = ListOffsetsResult.new(event_ptr)
423
+ list_offsets_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
424
+
425
+ if list_offsets_handle = Rdkafka::Admin::ListOffsetsHandle.remove(list_offsets_handle_ptr.address)
426
+ list_offsets_handle[:response] = list_offsets.result_error
427
+ list_offsets_handle[:response_string] = list_offsets.error_string
428
+ list_offsets_handle[:pending] = false
429
+
430
+ if list_offsets.result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
431
+ list_offsets_handle[:result_infos] = list_offsets.result_infos
432
+ list_offsets_handle[:result_count] = list_offsets.result_count
433
+ end
434
+
435
+ list_offsets_handle.unlock
436
+ end
437
+ end
395
438
  end
396
439
 
397
440
  # @private
@@ -452,14 +495,14 @@ module Rdkafka
452
495
 
453
496
  # FFI Function used for Create Topic and Delete Topic callbacks
454
497
  background_event_callback_function = FFI::Function.new(
455
- :void, [:pointer, :pointer, :pointer]
498
+ :void, [:pointer, :pointer, :pointer]
456
499
  ) do |client_ptr, event_ptr, opaque_ptr|
457
500
  BackgroundEventCallback.call(client_ptr, event_ptr, opaque_ptr)
458
501
  end
459
502
 
460
503
  # FFI Function used for Message Delivery callbacks
461
504
  delivery_callback_function = FFI::Function.new(
462
- :void, [:pointer, :pointer, :pointer]
505
+ :void, [:pointer, :pointer, :pointer]
463
506
  ) do |client_ptr, message_ptr, opaque_ptr|
464
507
  DeliveryCallback.call(client_ptr, message_ptr, opaque_ptr)
465
508
  end
@@ -6,7 +6,7 @@ module Rdkafka
6
6
  # configuration options is available on https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md.
7
7
  class Config
8
8
  # @private
9
- @@logger = Logger.new(STDOUT)
9
+ @@logger = Logger.new($stdout)
10
10
  # @private
11
11
  @@statistics_callback = nil
12
12
  # @private
@@ -33,7 +33,7 @@ module Rdkafka
33
33
  # Makes sure that there is a thread for consuming logs
34
34
  # We do not spawn thread immediately and we need to check if it operates to support forking
35
35
  def self.ensure_log_thread
36
- return if @@log_thread && @@log_thread.alive?
36
+ return if @@log_thread&.alive?
37
37
 
38
38
  @@log_mutex.synchronize do
39
39
  # Restart if dead (fork, crash)
@@ -74,7 +74,7 @@ module Rdkafka
74
74
  # @param callback [Proc, #call, nil] callable object or nil to clear
75
75
  # @return [nil]
76
76
  def self.statistics_callback=(callback)
77
- raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call) || callback == nil
77
+ raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call) || callback.nil?
78
78
  @@statistics_callback = callback
79
79
  end
80
80
 
@@ -89,10 +89,10 @@ module Rdkafka
89
89
  # If this callback is not set, global errors such as brokers becoming unavailable will only be sent to the logger, as defined by librdkafka.
90
90
  # The callback is called with an instance of RdKafka::Error.
91
91
  #
92
- # @param callback [Proc, #call] callable object to handle errors
92
+ # @param callback [Proc, #call, nil] callable object to handle errors or nil to clear
93
93
  # @return [nil]
94
94
  def self.error_callback=(callback)
95
- raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call)
95
+ raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call) || callback.nil?
96
96
  @@error_callback = callback
97
97
  end
98
98
 
@@ -109,7 +109,7 @@ module Rdkafka
109
109
  # @param callback [Proc, #call, nil] callable object to handle token refresh or nil to clear
110
110
  # @return [nil]
111
111
  def self.oauthbearer_token_refresh_callback=(callback)
112
- raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call) || callback == nil
112
+ raise TypeError.new("Callback has to be callable") unless callback.respond_to?(:call) || callback.nil?
113
113
  @@oauthbearer_token_refresh_callback = callback
114
114
  end
115
115
 
@@ -131,7 +131,7 @@ module Rdkafka
131
131
  # Required config that cannot be overwritten.
132
132
  REQUIRED_CONFIG = {
133
133
  # Enable log queues so we get callbacks in our own Ruby threads
134
- :"log.queue" => true
134
+ "log.queue": true
135
135
  }.freeze
136
136
 
137
137
  # Returns a new config with the provided options which are merged with {DEFAULT_CONFIG}.
@@ -168,10 +168,8 @@ module Rdkafka
168
168
 
169
169
  # Get notifications on partition assignment/revocation for the subscribed topics
170
170
  #
171
- # @param listener [Object, #on_partitions_assigned, #on_partitions_revoked] listener instance
172
- def consumer_rebalance_listener=(listener)
173
- @consumer_rebalance_listener = listener
174
- end
171
+ # @return [Object, #on_partitions_assigned, #on_partitions_revoked] listener instance
172
+ attr_writer :consumer_rebalance_listener
175
173
 
176
174
  # Should we use a single queue for the underlying consumer and events.
177
175
  #
@@ -184,10 +182,8 @@ module Rdkafka
184
182
  # It is recommended to use the defaults and only set it to `false` in advance multi-threaded
185
183
  # and complex cases where granular events handling control is needed.
186
184
  #
187
- # @param poll_set [Boolean]
188
- def consumer_poll_set=(poll_set)
189
- @consumer_poll_set = poll_set
190
- end
185
+ # @return [Boolean]
186
+ attr_writer :consumer_poll_set
191
187
 
192
188
  # Creates a consumer with this configuration.
193
189
  #
@@ -228,11 +224,13 @@ module Rdkafka
228
224
  # @param native_kafka_auto_start [Boolean] should the native kafka operations be started
229
225
  # automatically. Defaults to true. Set to false only when doing complex initialization.
230
226
  # @param native_kafka_poll_timeout_ms [Integer] ms poll time of the native Kafka
227
+ # @param run_polling_thread [Boolean] should the background polling thread be started.
228
+ # Defaults to true. Set to false when using the FD API for fiber scheduler integration.
231
229
  # @return [Producer] The created producer
232
230
  #
233
231
  # @raise [ConfigError] When the configuration contains invalid options
234
232
  # @raise [ClientCreationError] When the native client cannot be created
235
- def producer(native_kafka_auto_start: true, native_kafka_poll_timeout_ms: Defaults::NATIVE_KAFKA_POLL_TIMEOUT_MS)
233
+ def producer(native_kafka_auto_start: true, native_kafka_poll_timeout_ms: Defaults::NATIVE_KAFKA_POLL_TIMEOUT_MS, run_polling_thread: true)
236
234
  # Create opaque
237
235
  opaque = Opaque.new
238
236
  # Create Kafka config
@@ -247,7 +245,7 @@ module Rdkafka
247
245
  Rdkafka::Producer.new(
248
246
  Rdkafka::NativeKafka.new(
249
247
  kafka,
250
- run_polling_thread: true,
248
+ run_polling_thread: run_polling_thread,
251
249
  opaque: opaque,
252
250
  auto_start: native_kafka_auto_start,
253
251
  timeout_ms: native_kafka_poll_timeout_ms
@@ -263,11 +261,13 @@ module Rdkafka
263
261
  # @param native_kafka_auto_start [Boolean] should the native kafka operations be started
264
262
  # automatically. Defaults to true. Set to false only when doing complex initialization.
265
263
  # @param native_kafka_poll_timeout_ms [Integer] ms poll time of the native Kafka
264
+ # @param run_polling_thread [Boolean] should the background polling thread be started.
265
+ # Defaults to true. Set to false when using the FD API for fiber scheduler integration.
266
266
  # @return [Admin] The created admin instance
267
267
  #
268
268
  # @raise [ConfigError] When the configuration contains invalid options
269
269
  # @raise [ClientCreationError] When the native client cannot be created
270
- def admin(native_kafka_auto_start: true, native_kafka_poll_timeout_ms: Defaults::NATIVE_KAFKA_POLL_TIMEOUT_MS)
270
+ def admin(native_kafka_auto_start: true, native_kafka_poll_timeout_ms: Defaults::NATIVE_KAFKA_POLL_TIMEOUT_MS, run_polling_thread: true)
271
271
  opaque = Opaque.new
272
272
  config = native_config(opaque)
273
273
  Rdkafka::Bindings.rd_kafka_conf_set_background_event_cb(config, Rdkafka::Callbacks::BackgroundEventCallbackFunction)
@@ -277,7 +277,7 @@ module Rdkafka
277
277
  Rdkafka::Admin.new(
278
278
  Rdkafka::NativeKafka.new(
279
279
  kafka,
280
- run_polling_thread: true,
280
+ run_polling_thread: run_polling_thread,
281
281
  opaque: opaque,
282
282
  auto_start: native_kafka_auto_start,
283
283
  timeout_ms: native_kafka_poll_timeout_ms
@@ -383,7 +383,7 @@ module Rdkafka
383
383
  # @param delivery_report [Rdkafka::Producer::DeliveryReport] the delivery report
384
384
  # @param delivery_handle [Rdkafka::Producer::DeliveryHandle] the delivery handle
385
385
  def call_delivery_callback(delivery_report, delivery_handle)
386
- producer.call_delivery_callback(delivery_report, delivery_handle) if producer
386
+ producer&.call_delivery_callback(delivery_report, delivery_handle)
387
387
  end
388
388
 
389
389
  # Invokes the on_partitions_assigned callback on the rebalance listener if set