rdkafka 0.22.2 → 0.25.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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -3
  3. data/Gemfile +9 -0
  4. data/README.md +17 -14
  5. data/bin/verify_kafka_warnings +37 -0
  6. data/dist/{librdkafka-2.8.0.tar.gz → librdkafka-2.12.1.tar.gz} +0 -0
  7. data/docker-compose-ssl.yml +35 -0
  8. data/docker-compose.yml +1 -1
  9. data/lib/rdkafka/abstract_handle.rb +23 -5
  10. data/lib/rdkafka/admin/acl_binding_result.rb +1 -1
  11. data/lib/rdkafka/admin/config_resource_binding_result.rb +1 -0
  12. data/lib/rdkafka/admin/create_acl_handle.rb +3 -0
  13. data/lib/rdkafka/admin/create_acl_report.rb +3 -0
  14. data/lib/rdkafka/admin/create_partitions_handle.rb +3 -0
  15. data/lib/rdkafka/admin/create_partitions_report.rb +1 -0
  16. data/lib/rdkafka/admin/create_topic_handle.rb +3 -0
  17. data/lib/rdkafka/admin/create_topic_report.rb +3 -0
  18. data/lib/rdkafka/admin/delete_acl_handle.rb +3 -0
  19. data/lib/rdkafka/admin/delete_acl_report.rb +3 -0
  20. data/lib/rdkafka/admin/delete_groups_handle.rb +5 -0
  21. data/lib/rdkafka/admin/delete_groups_report.rb +3 -0
  22. data/lib/rdkafka/admin/delete_topic_handle.rb +3 -0
  23. data/lib/rdkafka/admin/delete_topic_report.rb +3 -0
  24. data/lib/rdkafka/admin/describe_acl_handle.rb +3 -0
  25. data/lib/rdkafka/admin/describe_acl_report.rb +3 -0
  26. data/lib/rdkafka/admin/describe_configs_handle.rb +3 -0
  27. data/lib/rdkafka/admin/describe_configs_report.rb +6 -0
  28. data/lib/rdkafka/admin/incremental_alter_configs_handle.rb +3 -0
  29. data/lib/rdkafka/admin/incremental_alter_configs_report.rb +6 -0
  30. data/lib/rdkafka/admin.rb +108 -113
  31. data/lib/rdkafka/bindings.rb +76 -30
  32. data/lib/rdkafka/callbacks.rb +71 -11
  33. data/lib/rdkafka/config.rb +21 -12
  34. data/lib/rdkafka/consumer/headers.rb +3 -2
  35. data/lib/rdkafka/consumer/message.rb +7 -3
  36. data/lib/rdkafka/consumer/partition.rb +6 -2
  37. data/lib/rdkafka/consumer/topic_partition_list.rb +11 -7
  38. data/lib/rdkafka/consumer.rb +41 -29
  39. data/lib/rdkafka/defaults.rb +106 -0
  40. data/lib/rdkafka/error.rb +16 -1
  41. data/lib/rdkafka/helpers/oauth.rb +45 -12
  42. data/lib/rdkafka/metadata.rb +29 -5
  43. data/lib/rdkafka/native_kafka.rb +26 -2
  44. data/lib/rdkafka/producer/delivery_report.rb +8 -4
  45. data/lib/rdkafka/producer/partitions_count_cache.rb +24 -14
  46. data/lib/rdkafka/producer.rb +52 -26
  47. data/lib/rdkafka/version.rb +6 -3
  48. data/lib/rdkafka.rb +1 -0
  49. data/rdkafka.gemspec +35 -13
  50. data/renovate.json +6 -25
  51. metadata +23 -124
  52. data/.github/CODEOWNERS +0 -3
  53. data/.github/FUNDING.yml +0 -1
  54. data/.github/workflows/ci_linux_x86_64_gnu.yml +0 -271
  55. data/.github/workflows/ci_linux_x86_64_musl.yml +0 -194
  56. data/.github/workflows/ci_macos_arm64.yml +0 -284
  57. data/.github/workflows/push_linux_x86_64_gnu.yml +0 -65
  58. data/.github/workflows/push_linux_x86_64_musl.yml +0 -79
  59. data/.github/workflows/push_macos_arm64.yml +0 -54
  60. data/.github/workflows/push_ruby.yml +0 -37
  61. data/.github/workflows/verify-action-pins.yml +0 -16
  62. data/.gitignore +0 -14
  63. data/.rspec +0 -2
  64. data/.ruby-gemset +0 -1
  65. data/.ruby-version +0 -1
  66. data/.yardopts +0 -2
  67. data/ext/README.md +0 -19
  68. data/ext/build_common.sh +0 -361
  69. data/ext/build_linux_x86_64_gnu.sh +0 -306
  70. data/ext/build_linux_x86_64_musl.sh +0 -763
  71. data/ext/build_macos_arm64.sh +0 -550
  72. data/spec/rdkafka/abstract_handle_spec.rb +0 -117
  73. data/spec/rdkafka/admin/create_acl_handle_spec.rb +0 -56
  74. data/spec/rdkafka/admin/create_acl_report_spec.rb +0 -18
  75. data/spec/rdkafka/admin/create_topic_handle_spec.rb +0 -52
  76. data/spec/rdkafka/admin/create_topic_report_spec.rb +0 -16
  77. data/spec/rdkafka/admin/delete_acl_handle_spec.rb +0 -85
  78. data/spec/rdkafka/admin/delete_acl_report_spec.rb +0 -72
  79. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +0 -52
  80. data/spec/rdkafka/admin/delete_topic_report_spec.rb +0 -16
  81. data/spec/rdkafka/admin/describe_acl_handle_spec.rb +0 -85
  82. data/spec/rdkafka/admin/describe_acl_report_spec.rb +0 -73
  83. data/spec/rdkafka/admin_spec.rb +0 -971
  84. data/spec/rdkafka/bindings_spec.rb +0 -199
  85. data/spec/rdkafka/callbacks_spec.rb +0 -20
  86. data/spec/rdkafka/config_spec.rb +0 -258
  87. data/spec/rdkafka/consumer/headers_spec.rb +0 -73
  88. data/spec/rdkafka/consumer/message_spec.rb +0 -139
  89. data/spec/rdkafka/consumer/partition_spec.rb +0 -57
  90. data/spec/rdkafka/consumer/topic_partition_list_spec.rb +0 -248
  91. data/spec/rdkafka/consumer_spec.rb +0 -1274
  92. data/spec/rdkafka/error_spec.rb +0 -89
  93. data/spec/rdkafka/metadata_spec.rb +0 -79
  94. data/spec/rdkafka/native_kafka_spec.rb +0 -130
  95. data/spec/rdkafka/producer/delivery_handle_spec.rb +0 -45
  96. data/spec/rdkafka/producer/delivery_report_spec.rb +0 -25
  97. data/spec/rdkafka/producer/partitions_count_cache_spec.rb +0 -359
  98. data/spec/rdkafka/producer_spec.rb +0 -1345
  99. data/spec/spec_helper.rb +0 -195
data/lib/rdkafka/admin.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rdkafka
4
+ # Admin client for Kafka administrative operations
4
5
  class Admin
5
6
  include Helpers::OAuth
6
7
 
@@ -8,7 +9,7 @@ module Rdkafka
8
9
  # Allows us to retrieve librdkafka errors with descriptions
9
10
  # Useful for debugging and building UIs, etc.
10
11
  #
11
- # @return [Hash<Integer, Hash>] hash with errors mapped by code
12
+ # @return [Hash{Integer => Hash}] hash with errors mapped by code
12
13
  def describe_errors
13
14
  # Memory pointers for the array of structures and count
14
15
  p_error_descs = FFI::MemoryPointer.new(:pointer)
@@ -49,6 +50,7 @@ module Rdkafka
49
50
  end
50
51
 
51
52
  # @private
53
+ # @param native_kafka [NativeKafka] wrapper around the native Kafka handle
52
54
  def initialize(native_kafka)
53
55
  @native_kafka = native_kafka
54
56
 
@@ -69,6 +71,8 @@ module Rdkafka
69
71
  end
70
72
  end
71
73
 
74
+ # @return [Proc] finalizer proc for closing the admin
75
+ # @private
72
76
  def finalizer
73
77
  ->(_) { close }
74
78
  end
@@ -78,7 +82,7 @@ module Rdkafka
78
82
  # @param topic_name [String, nil] metadat about particular topic or all if nil
79
83
  # @param timeout_ms [Integer] metadata request timeout
80
84
  # @return [Metadata] requested metadata
81
- def metadata(topic_name = nil, timeout_ms = 2_000)
85
+ def metadata(topic_name = nil, timeout_ms = Defaults::METADATA_TIMEOUT_MS)
82
86
  closed_admin_check(__method__)
83
87
 
84
88
  @native_kafka.with_inner do |inner|
@@ -100,9 +104,12 @@ module Rdkafka
100
104
 
101
105
  # Create a topic with the given partition count and replication factor
102
106
  #
107
+ # @param topic_name [String] name of the topic to create
108
+ # @param partition_count [Integer] number of partitions for the topic
109
+ # @param replication_factor [Integer] replication factor for the topic
110
+ # @param topic_config [Hash] optional topic configuration settings
103
111
  # @return [CreateTopicHandle] Create topic handle that can be used to wait for the result of
104
112
  # creating the topic
105
- #
106
113
  # @raise [ConfigError] When the partition count or replication factor are out of valid range
107
114
  # @raise [RdkafkaError] When the topic name is invalid or the topic already exists
108
115
  # @raise [RdkafkaError] When the topic configuration is invalid
@@ -149,7 +156,7 @@ module Rdkafka
149
156
  # Create and register the handle we will return to the caller
150
157
  create_topic_handle = CreateTopicHandle.new
151
158
  create_topic_handle[:pending] = true
152
- create_topic_handle[:response] = -1
159
+ create_topic_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
153
160
  CreateTopicHandle.register(create_topic_handle)
154
161
  admin_options_ptr = @native_kafka.with_inner do |inner|
155
162
  Rdkafka::Bindings.rd_kafka_AdminOptions_new(inner, Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATETOPICS)
@@ -178,6 +185,11 @@ module Rdkafka
178
185
  create_topic_handle
179
186
  end
180
187
 
188
+ # Deletes a consumer group
189
+ #
190
+ # @param group_id [String] the group id to delete
191
+ # @return [DeleteGroupsHandle] delete groups handle that can be used to wait for the result
192
+ # @raise [RdkafkaError] When deleting the group fails
181
193
  def delete_group(group_id)
182
194
  closed_admin_check(__method__)
183
195
 
@@ -202,7 +214,7 @@ module Rdkafka
202
214
  # Create and register the handle we will return to the caller
203
215
  delete_groups_handle = DeleteGroupsHandle.new
204
216
  delete_groups_handle[:pending] = true
205
- delete_groups_handle[:response] = -1
217
+ delete_groups_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
206
218
  DeleteGroupsHandle.register(delete_groups_handle)
207
219
  admin_options_ptr = @native_kafka.with_inner do |inner|
208
220
  Rdkafka::Bindings.rd_kafka_AdminOptions_new(inner, Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_DELETETOPICS)
@@ -233,6 +245,7 @@ module Rdkafka
233
245
 
234
246
  # Deletes the named topic
235
247
  #
248
+ # @param topic_name [String] name of the topic to delete
236
249
  # @return [DeleteTopicHandle] Delete topic handle that can be used to wait for the result of
237
250
  # deleting the topic
238
251
  # @raise [RdkafkaError] When the topic name is invalid or the topic does not exist
@@ -259,7 +272,7 @@ module Rdkafka
259
272
  # Create and register the handle we will return to the caller
260
273
  delete_topic_handle = DeleteTopicHandle.new
261
274
  delete_topic_handle[:pending] = true
262
- delete_topic_handle[:response] = -1
275
+ delete_topic_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
263
276
  DeleteTopicHandle.register(delete_topic_handle)
264
277
  admin_options_ptr = @native_kafka.with_inner do |inner|
265
278
  Rdkafka::Bindings.rd_kafka_AdminOptions_new(inner, Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_DELETETOPICS)
@@ -290,14 +303,12 @@ module Rdkafka
290
303
 
291
304
  # Creates extra partitions for a given topic
292
305
  #
293
- # @param topic_name [String]
306
+ # @param topic_name [String] name of the topic
294
307
  # @param partition_count [Integer] how many partitions we want to end up with for given topic
295
- #
308
+ # @return [CreatePartitionsHandle] Create partitions handle that can be used to wait for the result
296
309
  # @raise [ConfigError] When the partition count or replication factor are out of valid range
297
310
  # @raise [RdkafkaError] When the topic name is invalid or the topic already exists
298
311
  # @raise [RdkafkaError] When the topic configuration is invalid
299
- #
300
- # @return [CreateTopicHandle] Create topic handle that can be used to wait for the result of creating the topic
301
312
  def create_partitions(topic_name, partition_count)
302
313
  closed_admin_check(__method__)
303
314
 
@@ -327,7 +338,7 @@ module Rdkafka
327
338
  # Create and register the handle we will return to the caller
328
339
  create_partitions_handle = CreatePartitionsHandle.new
329
340
  create_partitions_handle[:pending] = true
330
- create_partitions_handle[:response] = -1
341
+ create_partitions_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
331
342
  CreatePartitionsHandle.register(create_partitions_handle)
332
343
  admin_options_ptr = Rdkafka::Bindings.rd_kafka_AdminOptions_new(inner, Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS)
333
344
  Rdkafka::Bindings.rd_kafka_AdminOptions_set_opaque(admin_options_ptr, create_partitions_handle.to_ptr)
@@ -354,40 +365,34 @@ module Rdkafka
354
365
  end
355
366
 
356
367
  # Create acl
357
- # @param resource_type - values of type rd_kafka_ResourceType_t
358
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
359
- # valid values are:
360
- # RD_KAFKA_RESOURCE_TOPIC = 2
361
- # RD_KAFKA_RESOURCE_GROUP = 3
362
- # RD_KAFKA_RESOURCE_BROKER = 4
363
- # @param resource_pattern_type - values of type rd_kafka_ResourcePatternType_t
364
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
365
- # valid values are:
366
- # RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
367
- # RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
368
- # RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
369
- # @param operation - values of type rd_kafka_AclOperation_t
370
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
371
- # valid values are:
372
- # RD_KAFKA_ACL_OPERATION_ALL = 2
373
- # RD_KAFKA_ACL_OPERATION_READ = 3
374
- # RD_KAFKA_ACL_OPERATION_WRITE = 4
375
- # RD_KAFKA_ACL_OPERATION_CREATE = 5
376
- # RD_KAFKA_ACL_OPERATION_DELETE = 6
377
- # RD_KAFKA_ACL_OPERATION_ALTER = 7
378
- # RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
379
- # RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
380
- # RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
381
- # RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
382
- # RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
383
- # @param permission_type - values of type rd_kafka_AclPermissionType_t
384
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
385
- # valid values are:
386
- # RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
387
- # RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
388
368
  #
369
+ # @param resource_type [Integer] rd_kafka_ResourceType_t value:
370
+ # - RD_KAFKA_RESOURCE_TOPIC = 2
371
+ # - RD_KAFKA_RESOURCE_GROUP = 3
372
+ # - RD_KAFKA_RESOURCE_BROKER = 4
373
+ # @param resource_name [String] name of the resource
374
+ # @param resource_pattern_type [Integer] rd_kafka_ResourcePatternType_t value:
375
+ # - RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
376
+ # - RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
377
+ # - RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
378
+ # @param principal [String] principal (e.g., "User:alice")
379
+ # @param host [String] host address
380
+ # @param operation [Integer] rd_kafka_AclOperation_t value:
381
+ # - RD_KAFKA_ACL_OPERATION_ALL = 2
382
+ # - RD_KAFKA_ACL_OPERATION_READ = 3
383
+ # - RD_KAFKA_ACL_OPERATION_WRITE = 4
384
+ # - RD_KAFKA_ACL_OPERATION_CREATE = 5
385
+ # - RD_KAFKA_ACL_OPERATION_DELETE = 6
386
+ # - RD_KAFKA_ACL_OPERATION_ALTER = 7
387
+ # - RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
388
+ # - RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
389
+ # - RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
390
+ # - RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
391
+ # - RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
392
+ # @param permission_type [Integer] rd_kafka_AclPermissionType_t value:
393
+ # - RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
394
+ # - RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
389
395
  # @return [CreateAclHandle] Create acl handle that can be used to wait for the result of creating the acl
390
- #
391
396
  # @raise [RdkafkaError]
392
397
  def create_acl(resource_type:, resource_name:, resource_pattern_type:, principal:, host:, operation:, permission_type:)
393
398
  closed_admin_check(__method__)
@@ -427,7 +432,7 @@ module Rdkafka
427
432
  # Create and register the handle that we will return to the caller
428
433
  create_acl_handle = CreateAclHandle.new
429
434
  create_acl_handle[:pending] = true
430
- create_acl_handle[:response] = -1
435
+ create_acl_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
431
436
  CreateAclHandle.register(create_acl_handle)
432
437
 
433
438
  admin_options_ptr = @native_kafka.with_inner do |inner|
@@ -460,39 +465,33 @@ module Rdkafka
460
465
 
461
466
  # Delete acl
462
467
  #
463
- # @param resource_type - values of type rd_kafka_ResourceType_t
464
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
465
- # valid values are:
466
- # RD_KAFKA_RESOURCE_TOPIC = 2
467
- # RD_KAFKA_RESOURCE_GROUP = 3
468
- # RD_KAFKA_RESOURCE_BROKER = 4
469
- # @param resource_pattern_type - values of type rd_kafka_ResourcePatternType_t
470
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
471
- # valid values are:
472
- # RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
473
- # RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
474
- # RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
475
- # @param operation - values of type rd_kafka_AclOperation_t
476
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
477
- # valid values are:
478
- # RD_KAFKA_ACL_OPERATION_ALL = 2
479
- # RD_KAFKA_ACL_OPERATION_READ = 3
480
- # RD_KAFKA_ACL_OPERATION_WRITE = 4
481
- # RD_KAFKA_ACL_OPERATION_CREATE = 5
482
- # RD_KAFKA_ACL_OPERATION_DELETE = 6
483
- # RD_KAFKA_ACL_OPERATION_ALTER = 7
484
- # RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
485
- # RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
486
- # RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
487
- # RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
488
- # RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
489
- # @param permission_type - values of type rd_kafka_AclPermissionType_t
490
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
491
- # valid values are:
492
- # RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
493
- # RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
468
+ # @param resource_type [Integer] rd_kafka_ResourceType_t value:
469
+ # - RD_KAFKA_RESOURCE_TOPIC = 2
470
+ # - RD_KAFKA_RESOURCE_GROUP = 3
471
+ # - RD_KAFKA_RESOURCE_BROKER = 4
472
+ # @param resource_name [String, nil] name of the resource or nil for any
473
+ # @param resource_pattern_type [Integer] rd_kafka_ResourcePatternType_t value:
474
+ # - RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
475
+ # - RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
476
+ # - RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
477
+ # @param principal [String, nil] principal (e.g., "User:alice") or nil for any
478
+ # @param host [String, nil] host address or nil for any
479
+ # @param operation [Integer] rd_kafka_AclOperation_t value:
480
+ # - RD_KAFKA_ACL_OPERATION_ALL = 2
481
+ # - RD_KAFKA_ACL_OPERATION_READ = 3
482
+ # - RD_KAFKA_ACL_OPERATION_WRITE = 4
483
+ # - RD_KAFKA_ACL_OPERATION_CREATE = 5
484
+ # - RD_KAFKA_ACL_OPERATION_DELETE = 6
485
+ # - RD_KAFKA_ACL_OPERATION_ALTER = 7
486
+ # - RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
487
+ # - RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
488
+ # - RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
489
+ # - RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
490
+ # - RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
491
+ # @param permission_type [Integer] rd_kafka_AclPermissionType_t value:
492
+ # - RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
493
+ # - RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
494
494
  # @return [DeleteAclHandle] Delete acl handle that can be used to wait for the result of deleting the acl
495
- #
496
495
  # @raise [RdkafkaError]
497
496
  def delete_acl(resource_type:, resource_name:, resource_pattern_type:, principal:, host:, operation:, permission_type:)
498
497
  closed_admin_check(__method__)
@@ -534,7 +533,7 @@ module Rdkafka
534
533
  # Create and register the handle that we will return to the caller
535
534
  delete_acl_handle = DeleteAclHandle.new
536
535
  delete_acl_handle[:pending] = true
537
- delete_acl_handle[:response] = -1
536
+ delete_acl_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
538
537
  DeleteAclHandle.register(delete_acl_handle)
539
538
 
540
539
  admin_options_ptr = @native_kafka.with_inner do |inner|
@@ -567,39 +566,33 @@ module Rdkafka
567
566
 
568
567
  # Describe acls
569
568
  #
570
- # @param resource_type - values of type rd_kafka_ResourceType_t
571
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
572
- # valid values are:
573
- # RD_KAFKA_RESOURCE_TOPIC = 2
574
- # RD_KAFKA_RESOURCE_GROUP = 3
575
- # RD_KAFKA_RESOURCE_BROKER = 4
576
- # @param resource_pattern_type - values of type rd_kafka_ResourcePatternType_t
577
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
578
- # valid values are:
579
- # RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
580
- # RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
581
- # RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
582
- # @param operation - values of type rd_kafka_AclOperation_t
583
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
584
- # valid values are:
585
- # RD_KAFKA_ACL_OPERATION_ALL = 2
586
- # RD_KAFKA_ACL_OPERATION_READ = 3
587
- # RD_KAFKA_ACL_OPERATION_WRITE = 4
588
- # RD_KAFKA_ACL_OPERATION_CREATE = 5
589
- # RD_KAFKA_ACL_OPERATION_DELETE = 6
590
- # RD_KAFKA_ACL_OPERATION_ALTER = 7
591
- # RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
592
- # RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
593
- # RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
594
- # RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
595
- # RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
596
- # @param permission_type - values of type rd_kafka_AclPermissionType_t
597
- # https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
598
- # valid values are:
599
- # RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
600
- # RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
569
+ # @param resource_type [Integer] rd_kafka_ResourceType_t value:
570
+ # - RD_KAFKA_RESOURCE_TOPIC = 2
571
+ # - RD_KAFKA_RESOURCE_GROUP = 3
572
+ # - RD_KAFKA_RESOURCE_BROKER = 4
573
+ # @param resource_name [String, nil] name of the resource or nil for any
574
+ # @param resource_pattern_type [Integer] rd_kafka_ResourcePatternType_t value:
575
+ # - RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
576
+ # - RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
577
+ # - RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
578
+ # @param principal [String, nil] principal (e.g., "User:alice") or nil for any
579
+ # @param host [String, nil] host address or nil for any
580
+ # @param operation [Integer] rd_kafka_AclOperation_t value:
581
+ # - RD_KAFKA_ACL_OPERATION_ALL = 2
582
+ # - RD_KAFKA_ACL_OPERATION_READ = 3
583
+ # - RD_KAFKA_ACL_OPERATION_WRITE = 4
584
+ # - RD_KAFKA_ACL_OPERATION_CREATE = 5
585
+ # - RD_KAFKA_ACL_OPERATION_DELETE = 6
586
+ # - RD_KAFKA_ACL_OPERATION_ALTER = 7
587
+ # - RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
588
+ # - RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
589
+ # - RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
590
+ # - RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
591
+ # - RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
592
+ # @param permission_type [Integer] rd_kafka_AclPermissionType_t value:
593
+ # - RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
594
+ # - RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
601
595
  # @return [DescribeAclHandle] Describe acl handle that can be used to wait for the result of fetching acls
602
- #
603
596
  # @raise [RdkafkaError]
604
597
  def describe_acl(resource_type:, resource_name:, resource_pattern_type:, principal:, host:, operation:, permission_type:)
605
598
  closed_admin_check(__method__)
@@ -634,7 +627,7 @@ module Rdkafka
634
627
  # Create and register the handle that we will return to the caller
635
628
  describe_acl_handle = DescribeAclHandle.new
636
629
  describe_acl_handle[:pending] = true
637
- describe_acl_handle[:response] = -1
630
+ describe_acl_handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
638
631
  DescribeAclHandle.register(describe_acl_handle)
639
632
 
640
633
  admin_options_ptr = @native_kafka.with_inner do |inner|
@@ -664,7 +657,6 @@ module Rdkafka
664
657
  describe_acl_handle
665
658
  end
666
659
 
667
-
668
660
  # Describe configs
669
661
  #
670
662
  # @param resources [Array<Hash>] Array where elements are hashes with two keys:
@@ -681,7 +673,7 @@ module Rdkafka
681
673
 
682
674
  handle = DescribeConfigsHandle.new
683
675
  handle[:pending] = true
684
- handle[:response] = -1
676
+ handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
685
677
 
686
678
  queue_ptr = @native_kafka.with_inner do |inner|
687
679
  Rdkafka::Bindings.rd_kafka_queue_get_background(inner)
@@ -754,7 +746,7 @@ module Rdkafka
754
746
 
755
747
  handle = IncrementalAlterConfigsHandle.new
756
748
  handle[:pending] = true
757
- handle[:response] = -1
749
+ handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
758
750
 
759
751
  queue_ptr = @native_kafka.with_inner do |inner|
760
752
  Rdkafka::Bindings.rd_kafka_queue_get_background(inner)
@@ -826,6 +818,9 @@ module Rdkafka
826
818
 
827
819
  private
828
820
 
821
+ # Checks if the admin is closed and raises an error if so
822
+ # @param method [Symbol] name of the calling method for error context
823
+ # @raise [ClosedAdminError] when the admin is closed
829
824
  def closed_admin_check(method)
830
825
  raise Rdkafka::ClosedAdminError.new(method) if closed?
831
826
  end
@@ -2,9 +2,20 @@
2
2
 
3
3
  module Rdkafka
4
4
  # @private
5
+ #
6
+ # @note
7
+ # There are two types of responses related to errors:
8
+ # - rd_kafka_error_t - a C object that we need to remap into an error or null when no error
9
+ # - rd_kafka_resp_err_t - response error code (numeric) that we can use directly
10
+ #
11
+ # It is critical to ensure, that we handle them correctly. The result type should be:
12
+ # - rd_kafka_error_t - :pointer
13
+ # - rd_kafka_resp_err_t - :int
5
14
  module Bindings
6
15
  extend FFI::Library
7
16
 
17
+ # Returns the library extension based on the host OS
18
+ # @return [String] 'dylib' on macOS, 'so' on other systems
8
19
  def self.lib_extension
9
20
  if RbConfig::CONFIG['host_os'] =~ /darwin/
10
21
  'dylib'
@@ -13,7 +24,39 @@ module Rdkafka
13
24
  end
14
25
  end
15
26
 
16
- ffi_lib File.join(__dir__, "../../ext/librdkafka.#{lib_extension}")
27
+ # Wrap ffi_lib to provide better error messages for glibc compatibility issues
28
+ begin
29
+ ffi_lib File.join(__dir__, "../../ext/librdkafka.#{lib_extension}")
30
+ rescue LoadError => e
31
+ error_message = e.message
32
+
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'
36
+
37
+ raise Rdkafka::LibraryLoadError, <<~ERROR_MSG.strip
38
+ Failed to load librdkafka due to glibc compatibility issue.
39
+
40
+ The precompiled librdkafka binary requires glibc version #{glibc_version} or higher,
41
+ but your system has an older version installed.
42
+
43
+ To resolve this issue, you have two options:
44
+
45
+ 1. Upgrade your system to a supported platform (recommended)
46
+
47
+ 2. Force compilation from source by reinstalling without the precompiled binary:
48
+ gem install rdkafka --platform=ruby
49
+
50
+ Or if using Bundler, add to your Gemfile:
51
+ gem 'rdkafka', force_ruby_platform: true
52
+
53
+ Original error: #{error_message}
54
+ ERROR_MSG
55
+ else
56
+ # Re-raise the original error if it's not a glibc issue
57
+ raise
58
+ end
59
+ end
17
60
 
18
61
  RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS = -175
19
62
  RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS = -174
@@ -26,8 +69,12 @@ module Rdkafka
26
69
  RD_KAFKA_OFFSET_STORED = -1000
27
70
  RD_KAFKA_OFFSET_INVALID = -1001
28
71
 
72
+ RD_KAFKA_PARTITION_UA = -1
73
+ RD_KAFKA_PARTITION_UA_STR = RD_KAFKA_PARTITION_UA.to_s.freeze
74
+
29
75
  EMPTY_HASH = {}.freeze
30
76
 
77
+ # FFI struct for size_t pointer wrapper
31
78
  class SizePtr < FFI::Struct
32
79
  layout :value, :size_t
33
80
  end
@@ -51,8 +98,7 @@ module Rdkafka
51
98
  attach_function :rd_kafka_metadata, [:pointer, :int, :pointer, :pointer, :int], :int, blocking: true
52
99
  attach_function :rd_kafka_metadata_destroy, [:pointer], :void, blocking: true
53
100
 
54
- # Message struct
55
-
101
+ # FFI struct representing a Kafka message (rd_kafka_message_t)
56
102
  class Message < FFI::Struct
57
103
  layout :err, :int,
58
104
  :rkt, :pointer,
@@ -71,8 +117,7 @@ module Rdkafka
71
117
  attach_function :rd_kafka_topic_destroy, [:pointer], :pointer
72
118
  attach_function :rd_kafka_topic_name, [:pointer], :string
73
119
 
74
- # TopicPartition ad TopicPartitionList structs
75
-
120
+ # FFI struct representing a topic partition (rd_kafka_topic_partition_t)
76
121
  class TopicPartition < FFI::Struct
77
122
  layout :topic, :string,
78
123
  :partition, :int32,
@@ -84,6 +129,7 @@ module Rdkafka
84
129
  :_private, :pointer
85
130
  end
86
131
 
132
+ # FFI struct representing a topic partition list (rd_kafka_topic_partition_list_t)
87
133
  class TopicPartitionList < FFI::Struct
88
134
  layout :cnt, :int,
89
135
  :size, :int,
@@ -91,17 +137,15 @@ module Rdkafka
91
137
  end
92
138
 
93
139
  attach_function :rd_kafka_topic_partition_list_new, [:int32], :pointer
94
- attach_function :rd_kafka_topic_partition_list_add, [:pointer, :string, :int32], :void
140
+ attach_function :rd_kafka_topic_partition_list_add, [:pointer, :string, :int32], :pointer
95
141
  attach_function :rd_kafka_topic_partition_list_set_offset, [:pointer, :string, :int32, :int64], :void
96
142
  attach_function :rd_kafka_topic_partition_list_destroy, [:pointer], :void
97
143
  attach_function :rd_kafka_topic_partition_list_copy, [:pointer], :pointer
98
144
 
99
- # Configs management
100
- #
101
- # Structs for management of configurations
102
- # Each configuration is attached to a resource and one resource can have many configuration
103
- # details. Each resource will also have separate errors results if obtaining configuration
104
- # was not possible for any reason
145
+ # FFI struct representing a config resource (rd_kafka_ConfigResource_t)
146
+ # Structs for management of configurations. Each configuration is attached to a resource
147
+ # and one resource can have many configuration details. Each resource will also have
148
+ # separate errors results if obtaining configuration was not possible for any reason
105
149
  class ConfigResource < FFI::Struct
106
150
  layout :type, :int,
107
151
  :name, :string
@@ -138,7 +182,7 @@ module Rdkafka
138
182
  RD_KAFKA_ALTER_CONFIG_OP_TYPE_APPEND = 2
139
183
  RD_KAFKA_ALTER_CONFIG_OP_TYPE_SUBTRACT = 3
140
184
 
141
- # Errors
185
+ # FFI struct for error description (rd_kafka_err_desc)
142
186
  class NativeErrorDesc < FFI::Struct
143
187
  layout :code, :int,
144
188
  :name, :pointer,
@@ -147,6 +191,10 @@ module Rdkafka
147
191
 
148
192
  attach_function :rd_kafka_err2name, [:int], :string
149
193
  attach_function :rd_kafka_err2str, [:int], :string
194
+ attach_function :rd_kafka_error_is_fatal, [:pointer], :int
195
+ attach_function :rd_kafka_error_is_retriable, [:pointer], :int
196
+ attach_function :rd_kafka_error_txn_requires_abort, [:pointer], :int
197
+ attach_function :rd_kafka_error_destroy, [:pointer], :void
150
198
  attach_function :rd_kafka_get_err_descs, [:pointer, :pointer], :void
151
199
 
152
200
  # Configuration
@@ -221,7 +269,7 @@ module Rdkafka
221
269
  # Since this cache is shared, having few consumers and/or producers in one process will
222
270
  # automatically improve the querying times even with low refresh times.
223
271
  (stats['topics'] || EMPTY_HASH).each do |topic_name, details|
224
- partitions_count = details['partitions'].keys.reject { |k| k == '-1' }.size
272
+ partitions_count = details['partitions'].keys.reject { |k| k == RD_KAFKA_PARTITION_UA_STR }.size
225
273
 
226
274
  next unless partitions_count.positive?
227
275
 
@@ -232,7 +280,7 @@ module Rdkafka
232
280
  end
233
281
 
234
282
  # Return 0 so librdkafka frees the json string
235
- 0
283
+ RD_KAFKA_RESP_ERR_NO_ERROR
236
284
  end
237
285
 
238
286
  ErrorCallback = FFI::Function.new(
@@ -355,7 +403,6 @@ module Rdkafka
355
403
  attach_function :rd_kafka_query_watermark_offsets, [:pointer, :string, :int, :pointer, :pointer, :int], :int
356
404
 
357
405
  # Producer
358
-
359
406
  RD_KAFKA_VTYPE_END = 0
360
407
  RD_KAFKA_VTYPE_TOPIC = 1
361
408
  RD_KAFKA_VTYPE_RKT = 2
@@ -377,16 +424,25 @@ module Rdkafka
377
424
  callback :delivery_cb, [:pointer, :pointer, :pointer], :void
378
425
  attach_function :rd_kafka_conf_set_dr_msg_cb, [:pointer, :delivery_cb], :void
379
426
 
380
- # Partitioner
427
+ # Hash mapping partitioner names to their FFI function symbols
428
+ # @return [Hash{String => Symbol}]
381
429
  PARTITIONERS = %w(random consistent consistent_random murmur2 murmur2_random fnv1a fnv1a_random).each_with_object({}) do |name, hsh|
382
430
  method_name = "rd_kafka_msg_partitioner_#{name}".to_sym
383
431
  attach_function method_name, [:pointer, :pointer, :size_t, :int32, :pointer, :pointer], :int32
384
432
  hsh[name] = method_name
385
433
  end
386
434
 
435
+ # Calculates the partition for a message based on the partitioner
436
+ #
437
+ # @param topic_ptr [FFI::Pointer] pointer to the topic handle
438
+ # @param str [String] the partition key string
439
+ # @param partition_count [Integer, nil] number of partitions
440
+ # @param partitioner [String] name of the partitioner to use
441
+ # @return [Integer] partition number or RD_KAFKA_PARTITION_UA if unassigned
442
+ # @raise [Rdkafka::Config::ConfigError] when an unknown partitioner is specified
387
443
  def self.partitioner(topic_ptr, str, partition_count, partitioner = "consistent_random")
388
444
  # Return RD_KAFKA_PARTITION_UA(unassigned partition) when partition count is nil/zero.
389
- return -1 unless partition_count&.nonzero?
445
+ return RD_KAFKA_PARTITION_UA unless partition_count&.nonzero?
390
446
 
391
447
  str_ptr = str.empty? ? FFI::MemoryPointer::NULL : FFI::MemoryPointer.from_string(str)
392
448
  method_name = PARTITIONERS.fetch(partitioner) do
@@ -397,7 +453,6 @@ module Rdkafka
397
453
  end
398
454
 
399
455
  # Create Topics
400
-
401
456
  RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
402
457
  RD_KAFKA_EVENT_CREATETOPICS_RESULT = 100 # rd_kafka_event_type_t
403
458
 
@@ -409,7 +464,6 @@ module Rdkafka
409
464
  attach_function :rd_kafka_CreateTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
410
465
 
411
466
  # Delete Topics
412
-
413
467
  RD_KAFKA_ADMIN_OP_DELETETOPICS = 2 # rd_kafka_admin_op_t
414
468
  RD_KAFKA_EVENT_DELETETOPICS_RESULT = 101 # rd_kafka_event_type_t
415
469
 
@@ -430,7 +484,6 @@ module Rdkafka
430
484
  attach_function :rd_kafka_CreatePartitions_result_topics, [:pointer, :pointer], :pointer
431
485
 
432
486
  # Delete Group
433
-
434
487
  RD_KAFKA_ADMIN_OP_DELETEGROUPS = 7 # rd_kafka_admin_op_t
435
488
  RD_KAFKA_EVENT_DELETEGROUPS_RESULT = 106 # rd_kafka_event_type_t
436
489
 
@@ -464,7 +517,6 @@ module Rdkafka
464
517
  attach_function :rd_kafka_topic_result_name, [:pointer], :pointer
465
518
 
466
519
  # Create Acls
467
-
468
520
  RD_KAFKA_ADMIN_OP_CREATEACLS = 9
469
521
  RD_KAFKA_EVENT_CREATEACLS_RESULT = 1024
470
522
 
@@ -473,7 +525,6 @@ module Rdkafka
473
525
  attach_function :rd_kafka_CreateAcls_result_acls, [:pointer, :pointer], :pointer
474
526
 
475
527
  # Delete Acls
476
-
477
528
  RD_KAFKA_ADMIN_OP_DELETEACLS = 11
478
529
  RD_KAFKA_EVENT_DELETEACLS_RESULT = 4096
479
530
 
@@ -484,7 +535,6 @@ module Rdkafka
484
535
  attach_function :rd_kafka_DeleteAcls_result_response_matching_acls, [:pointer, :pointer], :pointer
485
536
 
486
537
  # Describe Acls
487
-
488
538
  RD_KAFKA_ADMIN_OP_DESCRIBEACLS = 10
489
539
  RD_KAFKA_EVENT_DESCRIBEACLS_RESULT = 2048
490
540
 
@@ -506,7 +556,6 @@ module Rdkafka
506
556
  attach_function :rd_kafka_AclBinding_destroy, [:pointer], :void
507
557
 
508
558
  # rd_kafka_ResourceType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
509
-
510
559
  RD_KAFKA_RESOURCE_ANY = 1
511
560
  RD_KAFKA_RESOURCE_TOPIC = 2
512
561
  RD_KAFKA_RESOURCE_GROUP = 3
@@ -514,14 +563,12 @@ module Rdkafka
514
563
  RD_KAFKA_RESOURCE_TRANSACTIONAL_ID = 5
515
564
 
516
565
  # rd_kafka_ResourcePatternType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
517
-
518
566
  RD_KAFKA_RESOURCE_PATTERN_ANY = 1
519
567
  RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
520
568
  RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
521
569
  RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
522
570
 
523
571
  # rd_kafka_AclOperation_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
524
-
525
572
  RD_KAFKA_ACL_OPERATION_ANY = 1
526
573
  RD_KAFKA_ACL_OPERATION_ALL = 2
527
574
  RD_KAFKA_ACL_OPERATION_READ = 3
@@ -536,7 +583,6 @@ module Rdkafka
536
583
  RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
537
584
 
538
585
  # rd_kafka_AclPermissionType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
539
-
540
586
  RD_KAFKA_ACL_PERMISSION_TYPE_ANY = 1
541
587
  RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
542
588
  RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
@@ -550,8 +596,8 @@ module Rdkafka
550
596
  attach_function :rd_kafka_AclBinding_error, [:pointer], :pointer
551
597
 
552
598
 
553
- # Extracting data from group results
554
- class NativeError < FFI::Struct # rd_kafka_error_t
599
+ # FFI struct for native error (rd_kafka_error_t)
600
+ class NativeError < FFI::Struct
555
601
  layout :code, :int32,
556
602
  :errstr, :pointer,
557
603
  :fatal, :u_int8_t,