rdkafka 0.12.0 → 0.15.1

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 (86) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/workflows/ci.yml +57 -0
  5. data/.gitignore +4 -0
  6. data/.rspec +1 -0
  7. data/.ruby-gemset +1 -0
  8. data/.ruby-version +1 -0
  9. data/CHANGELOG.md +155 -93
  10. data/Gemfile +2 -0
  11. data/{LICENSE → MIT-LICENSE} +2 -1
  12. data/README.md +76 -29
  13. data/Rakefile +2 -0
  14. data/certs/cert_chain.pem +26 -0
  15. data/docker-compose.yml +18 -15
  16. data/ext/README.md +1 -1
  17. data/ext/Rakefile +46 -27
  18. data/lib/rdkafka/abstract_handle.rb +41 -25
  19. data/lib/rdkafka/admin/acl_binding_result.rb +51 -0
  20. data/lib/rdkafka/admin/create_acl_handle.rb +28 -0
  21. data/lib/rdkafka/admin/create_acl_report.rb +24 -0
  22. data/lib/rdkafka/admin/create_partitions_handle.rb +27 -0
  23. data/lib/rdkafka/admin/create_partitions_report.rb +6 -0
  24. data/lib/rdkafka/admin/create_topic_handle.rb +2 -0
  25. data/lib/rdkafka/admin/create_topic_report.rb +2 -0
  26. data/lib/rdkafka/admin/delete_acl_handle.rb +30 -0
  27. data/lib/rdkafka/admin/delete_acl_report.rb +23 -0
  28. data/lib/rdkafka/admin/delete_groups_handle.rb +28 -0
  29. data/lib/rdkafka/admin/delete_groups_report.rb +24 -0
  30. data/lib/rdkafka/admin/delete_topic_handle.rb +2 -0
  31. data/lib/rdkafka/admin/delete_topic_report.rb +2 -0
  32. data/lib/rdkafka/admin/describe_acl_handle.rb +30 -0
  33. data/lib/rdkafka/admin/describe_acl_report.rb +23 -0
  34. data/lib/rdkafka/admin.rb +494 -35
  35. data/lib/rdkafka/bindings.rb +180 -41
  36. data/lib/rdkafka/callbacks.rb +202 -1
  37. data/lib/rdkafka/config.rb +62 -25
  38. data/lib/rdkafka/consumer/headers.rb +24 -9
  39. data/lib/rdkafka/consumer/message.rb +3 -1
  40. data/lib/rdkafka/consumer/partition.rb +2 -0
  41. data/lib/rdkafka/consumer/topic_partition_list.rb +13 -8
  42. data/lib/rdkafka/consumer.rb +243 -111
  43. data/lib/rdkafka/error.rb +15 -0
  44. data/lib/rdkafka/helpers/time.rb +14 -0
  45. data/lib/rdkafka/metadata.rb +25 -2
  46. data/lib/rdkafka/native_kafka.rb +120 -0
  47. data/lib/rdkafka/producer/delivery_handle.rb +16 -2
  48. data/lib/rdkafka/producer/delivery_report.rb +22 -2
  49. data/lib/rdkafka/producer.rb +151 -21
  50. data/lib/rdkafka/version.rb +5 -3
  51. data/lib/rdkafka.rb +24 -2
  52. data/rdkafka.gemspec +21 -5
  53. data/renovate.json +6 -0
  54. data/spec/rdkafka/abstract_handle_spec.rb +1 -1
  55. data/spec/rdkafka/admin/create_acl_handle_spec.rb +56 -0
  56. data/spec/rdkafka/admin/create_acl_report_spec.rb +18 -0
  57. data/spec/rdkafka/admin/create_topic_handle_spec.rb +1 -1
  58. data/spec/rdkafka/admin/create_topic_report_spec.rb +1 -1
  59. data/spec/rdkafka/admin/delete_acl_handle_spec.rb +85 -0
  60. data/spec/rdkafka/admin/delete_acl_report_spec.rb +72 -0
  61. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +1 -1
  62. data/spec/rdkafka/admin/delete_topic_report_spec.rb +1 -1
  63. data/spec/rdkafka/admin/describe_acl_handle_spec.rb +85 -0
  64. data/spec/rdkafka/admin/describe_acl_report_spec.rb +73 -0
  65. data/spec/rdkafka/admin_spec.rb +209 -5
  66. data/spec/rdkafka/bindings_spec.rb +2 -1
  67. data/spec/rdkafka/callbacks_spec.rb +1 -1
  68. data/spec/rdkafka/config_spec.rb +24 -3
  69. data/spec/rdkafka/consumer/headers_spec.rb +60 -0
  70. data/spec/rdkafka/consumer/message_spec.rb +1 -1
  71. data/spec/rdkafka/consumer/partition_spec.rb +1 -1
  72. data/spec/rdkafka/consumer/topic_partition_list_spec.rb +20 -1
  73. data/spec/rdkafka/consumer_spec.rb +352 -61
  74. data/spec/rdkafka/error_spec.rb +1 -1
  75. data/spec/rdkafka/metadata_spec.rb +4 -3
  76. data/spec/rdkafka/{producer/client_spec.rb → native_kafka_spec.rb} +13 -35
  77. data/spec/rdkafka/producer/delivery_handle_spec.rb +4 -1
  78. data/spec/rdkafka/producer/delivery_report_spec.rb +11 -3
  79. data/spec/rdkafka/producer_spec.rb +234 -22
  80. data/spec/spec_helper.rb +20 -2
  81. data.tar.gz.sig +0 -0
  82. metadata +81 -17
  83. metadata.gz.sig +0 -0
  84. data/.semaphore/semaphore.yml +0 -23
  85. data/bin/console +0 -11
  86. data/lib/rdkafka/producer/client.rb +0 -47
@@ -1,6 +1,4 @@
1
- require "ffi"
2
- require "json"
3
- require "logger"
1
+ # frozen_string_literal: true
4
2
 
5
3
  module Rdkafka
6
4
  # @private
@@ -15,7 +13,7 @@ module Rdkafka
15
13
  end
16
14
  end
17
15
 
18
- ffi_lib File.join(File.dirname(__FILE__), "../../ext/librdkafka.#{lib_extension}")
16
+ ffi_lib File.join(__dir__, "../../ext/librdkafka.#{lib_extension}")
19
17
 
20
18
  RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS = -175
21
19
  RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS = -174
@@ -33,15 +31,17 @@ module Rdkafka
33
31
 
34
32
  # Polling
35
33
 
36
- attach_function :rd_kafka_poll, [:pointer, :int], :void, blocking: true
34
+ attach_function :rd_kafka_flush, [:pointer, :int], :int, blocking: true
35
+ attach_function :rd_kafka_poll, [:pointer, :int], :int, blocking: true
37
36
  attach_function :rd_kafka_outq_len, [:pointer], :int, blocking: true
38
37
 
39
38
  # Metadata
40
39
 
41
- attach_function :rd_kafka_memberid, [:pointer], :string
42
- attach_function :rd_kafka_clusterid, [:pointer], :string
43
- attach_function :rd_kafka_metadata, [:pointer, :int, :pointer, :pointer, :int], :int
44
- attach_function :rd_kafka_metadata_destroy, [:pointer], :void
40
+ attach_function :rd_kafka_name, [:pointer], :string, blocking: true
41
+ attach_function :rd_kafka_memberid, [:pointer], :string, blocking: true
42
+ attach_function :rd_kafka_clusterid, [:pointer], :string, blocking: true
43
+ attach_function :rd_kafka_metadata, [:pointer, :int, :pointer, :pointer, :int], :int, blocking: true
44
+ attach_function :rd_kafka_metadata_destroy, [:pointer], :void, blocking: true
45
45
 
46
46
  # Message struct
47
47
 
@@ -110,6 +110,7 @@ module Rdkafka
110
110
  attach_function :rd_kafka_conf_set_stats_cb, [:pointer, :stats_cb], :void
111
111
  callback :error_cb, [:pointer, :int, :string, :pointer], :void
112
112
  attach_function :rd_kafka_conf_set_error_cb, [:pointer, :error_cb], :void
113
+ attach_function :rd_kafka_rebalance_protocol, [:pointer], :string
113
114
 
114
115
  # Log queue
115
116
  attach_function :rd_kafka_set_log_queue, [:pointer, :pointer], :void
@@ -153,6 +154,7 @@ module Rdkafka
153
154
  ) do |_client_prr, err_code, reason, _opaque|
154
155
  if Rdkafka::Config.error_callback
155
156
  error = Rdkafka::RdkafkaError.new(err_code, broker_message: reason)
157
+ error.set_backtrace(caller)
156
158
  Rdkafka::Config.error_callback.call(error)
157
159
  end
158
160
  end
@@ -165,24 +167,33 @@ module Rdkafka
165
167
  ]
166
168
 
167
169
  attach_function :rd_kafka_new, [:kafka_type, :pointer, :pointer, :int], :pointer
170
+
168
171
  attach_function :rd_kafka_destroy, [:pointer], :void
169
172
 
170
173
  # Consumer
171
174
 
172
- attach_function :rd_kafka_subscribe, [:pointer, :pointer], :int
173
- attach_function :rd_kafka_unsubscribe, [:pointer], :int
174
- attach_function :rd_kafka_subscription, [:pointer, :pointer], :int
175
- attach_function :rd_kafka_assign, [:pointer, :pointer], :int
176
- attach_function :rd_kafka_assignment, [:pointer, :pointer], :int
177
- attach_function :rd_kafka_committed, [:pointer, :pointer, :int], :int
175
+ attach_function :rd_kafka_subscribe, [:pointer, :pointer], :int, blocking: true
176
+ attach_function :rd_kafka_unsubscribe, [:pointer], :int, blocking: true
177
+ attach_function :rd_kafka_subscription, [:pointer, :pointer], :int, blocking: true
178
+ attach_function :rd_kafka_assign, [:pointer, :pointer], :int, blocking: true
179
+ attach_function :rd_kafka_incremental_assign, [:pointer, :pointer], :int, blocking: true
180
+ attach_function :rd_kafka_incremental_unassign, [:pointer, :pointer], :int, blocking: true
181
+ attach_function :rd_kafka_assignment, [:pointer, :pointer], :int, blocking: true
182
+ attach_function :rd_kafka_assignment_lost, [:pointer], :int, blocking: true
183
+ attach_function :rd_kafka_committed, [:pointer, :pointer, :int], :int, blocking: true
178
184
  attach_function :rd_kafka_commit, [:pointer, :pointer, :bool], :int, blocking: true
179
- attach_function :rd_kafka_poll_set_consumer, [:pointer], :void
185
+ attach_function :rd_kafka_poll_set_consumer, [:pointer], :void, blocking: true
180
186
  attach_function :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: true
181
187
  attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
182
- attach_function :rd_kafka_offset_store, [:pointer, :int32, :int64], :int
183
- attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int
184
- attach_function :rd_kafka_resume_partitions, [:pointer, :pointer], :int
185
- attach_function :rd_kafka_seek, [:pointer, :int32, :int64, :int], :int
188
+ attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
189
+ attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
190
+ attach_function :rd_kafka_resume_partitions, [:pointer, :pointer], :int, blocking: true
191
+ attach_function :rd_kafka_seek, [:pointer, :int32, :int64, :int], :int, blocking: true
192
+ attach_function :rd_kafka_offsets_for_times, [:pointer, :pointer, :int], :int, blocking: true
193
+ attach_function :rd_kafka_position, [:pointer, :pointer], :int, blocking: true
194
+ # those two are used for eos support
195
+ attach_function :rd_kafka_consumer_group_metadata, [:pointer], :pointer, blocking: true
196
+ attach_function :rd_kafka_consumer_group_metadata_destroy, [:pointer], :void, blocking: true
186
197
 
187
198
  # Headers
188
199
  attach_function :rd_kafka_header_get_all, [:pointer, :size_t, :pointer, :pointer, SizePtr], :int
@@ -191,30 +202,36 @@ module Rdkafka
191
202
  # Rebalance
192
203
 
193
204
  callback :rebalance_cb_function, [:pointer, :int, :pointer, :pointer], :void
194
- attach_function :rd_kafka_conf_set_rebalance_cb, [:pointer, :rebalance_cb_function], :void
205
+ attach_function :rd_kafka_conf_set_rebalance_cb, [:pointer, :rebalance_cb_function], :void, blocking: true
195
206
 
196
207
  RebalanceCallback = FFI::Function.new(
197
208
  :void, [:pointer, :int, :pointer, :pointer]
198
209
  ) do |client_ptr, code, partitions_ptr, opaque_ptr|
199
210
  case code
200
211
  when RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS
201
- Rdkafka::Bindings.rd_kafka_assign(client_ptr, partitions_ptr)
212
+ if Rdkafka::Bindings.rd_kafka_rebalance_protocol(client_ptr) == "COOPERATIVE"
213
+ Rdkafka::Bindings.rd_kafka_incremental_assign(client_ptr, partitions_ptr)
214
+ else
215
+ Rdkafka::Bindings.rd_kafka_assign(client_ptr, partitions_ptr)
216
+ end
202
217
  else # RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS or errors
203
- Rdkafka::Bindings.rd_kafka_assign(client_ptr, FFI::Pointer::NULL)
218
+ if Rdkafka::Bindings.rd_kafka_rebalance_protocol(client_ptr) == "COOPERATIVE"
219
+ Rdkafka::Bindings.rd_kafka_incremental_unassign(client_ptr, partitions_ptr)
220
+ else
221
+ Rdkafka::Bindings.rd_kafka_assign(client_ptr, FFI::Pointer::NULL)
222
+ end
204
223
  end
205
224
 
206
225
  opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
207
226
  return unless opaque
208
227
 
209
228
  tpl = Rdkafka::Consumer::TopicPartitionList.from_native_tpl(partitions_ptr).freeze
210
- consumer = Rdkafka::Consumer.new(client_ptr)
211
-
212
229
  begin
213
230
  case code
214
231
  when RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS
215
- opaque.call_on_partitions_assigned(consumer, tpl)
232
+ opaque.call_on_partitions_assigned(tpl)
216
233
  when RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS
217
- opaque.call_on_partitions_revoked(consumer, tpl)
234
+ opaque.call_on_partitions_revoked(tpl)
218
235
  end
219
236
  rescue Exception => err
220
237
  Rdkafka::Config.logger.error("Unhandled exception: #{err.class} - #{err.message}")
@@ -238,10 +255,13 @@ module Rdkafka
238
255
  RD_KAFKA_VTYPE_TIMESTAMP = 8
239
256
  RD_KAFKA_VTYPE_HEADER = 9
240
257
  RD_KAFKA_VTYPE_HEADERS = 10
258
+ RD_KAFKA_PURGE_F_QUEUE = 1
259
+ RD_KAFKA_PURGE_F_INFLIGHT = 2
241
260
 
242
261
  RD_KAFKA_MSG_F_COPY = 0x2
243
262
 
244
- attach_function :rd_kafka_producev, [:pointer, :varargs], :int
263
+ attach_function :rd_kafka_producev, [:pointer, :varargs], :int, blocking: true
264
+ attach_function :rd_kafka_purge, [:pointer, :int], :int, blocking: true
245
265
  callback :delivery_cb, [:pointer, :pointer, :pointer], :void
246
266
  attach_function :rd_kafka_conf_set_dr_msg_cb, [:pointer, :delivery_cb], :void
247
267
 
@@ -256,11 +276,11 @@ module Rdkafka
256
276
  # Return RD_KAFKA_PARTITION_UA(unassigned partition) when partition count is nil/zero.
257
277
  return -1 unless partition_count&.nonzero?
258
278
 
259
- str_ptr = FFI::MemoryPointer.from_string(str)
279
+ str_ptr = str.empty? ? FFI::MemoryPointer::NULL : FFI::MemoryPointer.from_string(str)
260
280
  method_name = PARTITIONERS.fetch(partitioner_name) do
261
281
  raise Rdkafka::Config::ConfigError.new("Unknown partitioner: #{partitioner_name}")
262
282
  end
263
- public_send(method_name, nil, str_ptr, str.size, partition_count, nil, nil)
283
+ public_send(method_name, nil, str_ptr, str.size > 0 ? str.size : 1, partition_count, nil, nil)
264
284
  end
265
285
 
266
286
  # Create Topics
@@ -268,23 +288,44 @@ module Rdkafka
268
288
  RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
269
289
  RD_KAFKA_EVENT_CREATETOPICS_RESULT = 100 # rd_kafka_event_type_t
270
290
 
271
- attach_function :rd_kafka_CreateTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
272
- attach_function :rd_kafka_NewTopic_new, [:pointer, :size_t, :size_t, :pointer, :size_t], :pointer
273
- attach_function :rd_kafka_NewTopic_set_config, [:pointer, :string, :string], :int32
274
- attach_function :rd_kafka_NewTopic_destroy, [:pointer], :void
275
- attach_function :rd_kafka_event_CreateTopics_result, [:pointer], :pointer
276
- attach_function :rd_kafka_CreateTopics_result_topics, [:pointer, :pointer], :pointer
291
+ attach_function :rd_kafka_CreateTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
292
+ attach_function :rd_kafka_NewTopic_new, [:pointer, :size_t, :size_t, :pointer, :size_t], :pointer, blocking: true
293
+ attach_function :rd_kafka_NewTopic_set_config, [:pointer, :string, :string], :int32, blocking: true
294
+ attach_function :rd_kafka_NewTopic_destroy, [:pointer], :void, blocking: true
295
+ attach_function :rd_kafka_event_CreateTopics_result, [:pointer], :pointer, blocking: true
296
+ attach_function :rd_kafka_CreateTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
277
297
 
278
298
  # Delete Topics
279
299
 
280
300
  RD_KAFKA_ADMIN_OP_DELETETOPICS = 2 # rd_kafka_admin_op_t
281
301
  RD_KAFKA_EVENT_DELETETOPICS_RESULT = 101 # rd_kafka_event_type_t
282
302
 
283
- attach_function :rd_kafka_DeleteTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :int32
284
- attach_function :rd_kafka_DeleteTopic_new, [:pointer], :pointer
285
- attach_function :rd_kafka_DeleteTopic_destroy, [:pointer], :void
286
- attach_function :rd_kafka_event_DeleteTopics_result, [:pointer], :pointer
287
- attach_function :rd_kafka_DeleteTopics_result_topics, [:pointer, :pointer], :pointer
303
+ attach_function :rd_kafka_DeleteTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :int32, blocking: true
304
+ attach_function :rd_kafka_DeleteTopic_new, [:pointer], :pointer, blocking: true
305
+ attach_function :rd_kafka_DeleteTopic_destroy, [:pointer], :void, blocking: true
306
+ attach_function :rd_kafka_event_DeleteTopics_result, [:pointer], :pointer, blocking: true
307
+ attach_function :rd_kafka_DeleteTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
308
+
309
+ # Create partitions
310
+ RD_KAFKA_ADMIN_OP_CREATEPARTITIONS = 3
311
+ RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT = 102
312
+
313
+ attach_function :rd_kafka_CreatePartitions, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
314
+ attach_function :rd_kafka_NewPartitions_new, %i[pointer size_t pointer size_t], :pointer
315
+ attach_function :rd_kafka_NewPartitions_destroy, [:pointer], :void
316
+ attach_function :rd_kafka_event_CreatePartitions_result, [:pointer], :pointer
317
+ attach_function :rd_kafka_CreatePartitions_result_topics, [:pointer, :pointer], :pointer
318
+
319
+ # Delete Group
320
+
321
+ RD_KAFKA_ADMIN_OP_DELETEGROUPS = 7 # rd_kafka_admin_op_t
322
+ RD_KAFKA_EVENT_DELETEGROUPS_RESULT = 106 # rd_kafka_event_type_t
323
+
324
+ attach_function :rd_kafka_DeleteGroups, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
325
+ attach_function :rd_kafka_DeleteGroup_new, [:pointer], :pointer, blocking: true
326
+ attach_function :rd_kafka_DeleteGroup_destroy, [:pointer], :void, blocking: true
327
+ attach_function :rd_kafka_event_DeleteGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteGroups_result_t*
328
+ attach_function :rd_kafka_DeleteGroups_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteGroups_result_t*, size_t* => rd_kafka_group_result_t**
288
329
 
289
330
  # Background Queue and Callback
290
331
 
@@ -308,5 +349,103 @@ module Rdkafka
308
349
  attach_function :rd_kafka_topic_result_error, [:pointer], :int32
309
350
  attach_function :rd_kafka_topic_result_error_string, [:pointer], :pointer
310
351
  attach_function :rd_kafka_topic_result_name, [:pointer], :pointer
352
+
353
+ # Create Acls
354
+
355
+ RD_KAFKA_ADMIN_OP_CREATEACLS = 9
356
+ RD_KAFKA_EVENT_CREATEACLS_RESULT = 1024
357
+
358
+ attach_function :rd_kafka_CreateAcls, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
359
+ attach_function :rd_kafka_event_CreateAcls_result, [:pointer], :pointer
360
+ attach_function :rd_kafka_CreateAcls_result_acls, [:pointer, :pointer], :pointer
361
+
362
+ # Delete Acls
363
+
364
+ RD_KAFKA_ADMIN_OP_DELETEACLS = 11
365
+ RD_KAFKA_EVENT_DELETEACLS_RESULT = 4096
366
+
367
+ attach_function :rd_kafka_DeleteAcls, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
368
+ attach_function :rd_kafka_event_DeleteAcls_result, [:pointer], :pointer
369
+ attach_function :rd_kafka_DeleteAcls_result_responses, [:pointer, :pointer], :pointer
370
+ attach_function :rd_kafka_DeleteAcls_result_response_error, [:pointer], :pointer
371
+ attach_function :rd_kafka_DeleteAcls_result_response_matching_acls, [:pointer, :pointer], :pointer
372
+
373
+ # Describe Acls
374
+
375
+ RD_KAFKA_ADMIN_OP_DESCRIBEACLS = 10
376
+ RD_KAFKA_EVENT_DESCRIBEACLS_RESULT = 2048
377
+
378
+ attach_function :rd_kafka_DescribeAcls, [:pointer, :pointer, :pointer, :pointer], :void
379
+ attach_function :rd_kafka_event_DescribeAcls_result, [:pointer], :pointer
380
+ attach_function :rd_kafka_DescribeAcls_result_acls, [:pointer, :pointer], :pointer
381
+
382
+ # Acl Bindings
383
+
384
+ attach_function :rd_kafka_AclBinding_restype, [:pointer], :int32
385
+ attach_function :rd_kafka_AclBinding_name, [:pointer], :pointer
386
+ attach_function :rd_kafka_AclBinding_resource_pattern_type, [:pointer], :int32
387
+ attach_function :rd_kafka_AclBinding_principal, [:pointer], :pointer
388
+ attach_function :rd_kafka_AclBinding_host, [:pointer], :pointer
389
+ attach_function :rd_kafka_AclBinding_operation, [:pointer], :int32
390
+ attach_function :rd_kafka_AclBinding_permission_type, [:pointer], :int32
391
+ attach_function :rd_kafka_AclBinding_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t ], :pointer
392
+ attach_function :rd_kafka_AclBindingFilter_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t ], :pointer
393
+ attach_function :rd_kafka_AclBinding_destroy, [:pointer], :void
394
+
395
+ # rd_kafka_ResourceType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
396
+
397
+ RD_KAFKA_RESOURCE_ANY = 1
398
+ RD_KAFKA_RESOURCE_TOPIC = 2
399
+ RD_KAFKA_RESOURCE_GROUP = 3
400
+ RD_KAFKA_RESOURCE_BROKER = 4
401
+
402
+ # rd_kafka_ResourcePatternType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
403
+
404
+ RD_KAFKA_RESOURCE_PATTERN_ANY = 1
405
+ RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
406
+ RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
407
+ RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
408
+
409
+ # rd_kafka_AclOperation_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
410
+
411
+ RD_KAFKA_ACL_OPERATION_ANY = 1
412
+ RD_KAFKA_ACL_OPERATION_ALL = 2
413
+ RD_KAFKA_ACL_OPERATION_READ = 3
414
+ RD_KAFKA_ACL_OPERATION_WRITE = 4
415
+ RD_KAFKA_ACL_OPERATION_CREATE = 5
416
+ RD_KAFKA_ACL_OPERATION_DELETE = 6
417
+ RD_KAFKA_ACL_OPERATION_ALTER = 7
418
+ RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
419
+ RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
420
+ RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
421
+ RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
422
+ RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
423
+
424
+ # rd_kafka_AclPermissionType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
425
+
426
+ RD_KAFKA_ACL_PERMISSION_TYPE_ANY = 1
427
+ RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
428
+ RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
429
+
430
+ # Extracting error details from Acl results
431
+ attach_function :rd_kafka_acl_result_error, [:pointer], :pointer
432
+ attach_function :rd_kafka_error_code, [:pointer], :int32
433
+ attach_function :rd_kafka_error_string, [:pointer], :pointer
434
+ attach_function :rd_kafka_event_error, [:pointer], :int32
435
+ attach_function :rd_kafka_event_error_string, [:pointer], :pointer
436
+ attach_function :rd_kafka_AclBinding_error, [:pointer], :pointer
437
+
438
+
439
+ # Extracting data from group results
440
+ class NativeError < FFI::Struct # rd_kafka_error_t
441
+ layout :code, :int32,
442
+ :errstr, :pointer,
443
+ :fatal, :u_int8_t,
444
+ :retriable, :u_int8_t,
445
+ :txn_requires_abort, :u_int8_t
446
+ end
447
+
448
+ attach_function :rd_kafka_group_result_error, [:pointer], NativeError.by_ref # rd_kafka_group_result_t* => rd_kafka_error_t*
449
+ attach_function :rd_kafka_group_result_name, [:pointer], :pointer
311
450
  end
312
451
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
4
  module Callbacks
3
5
 
@@ -21,6 +23,96 @@ module Rdkafka
21
23
  end
22
24
  end
23
25
 
26
+ class GroupResult
27
+ attr_reader :result_error, :error_string, :result_name
28
+ def initialize(group_result_pointer)
29
+ native_error = Rdkafka::Bindings.rd_kafka_group_result_error(group_result_pointer)
30
+
31
+ if native_error.null?
32
+ @result_error = 0
33
+ @error_string = FFI::Pointer::NULL
34
+ else
35
+ @result_error = native_error[:code]
36
+ @error_string = native_error[:errstr]
37
+ end
38
+
39
+ @result_name = Rdkafka::Bindings.rd_kafka_group_result_name(group_result_pointer)
40
+ end
41
+ def self.create_group_results_from_array(count, array_pointer)
42
+ (1..count).map do |index|
43
+ result_pointer = (array_pointer + (index - 1)).read_pointer
44
+ new(result_pointer)
45
+ end
46
+ end
47
+ end
48
+
49
+ # Extracts attributes of rd_kafka_acl_result_t
50
+ #
51
+ # @private
52
+ class CreateAclResult
53
+ attr_reader :result_error, :error_string
54
+
55
+ def initialize(acl_result_pointer)
56
+ rd_kafka_error_pointer = Bindings.rd_kafka_acl_result_error(acl_result_pointer)
57
+ @result_error = Rdkafka::Bindings.rd_kafka_error_code(rd_kafka_error_pointer)
58
+ @error_string = Rdkafka::Bindings.rd_kafka_error_string(rd_kafka_error_pointer)
59
+ end
60
+
61
+ def self.create_acl_results_from_array(count, array_pointer)
62
+ (1..count).map do |index|
63
+ result_pointer = (array_pointer + (index - 1)).read_pointer
64
+ new(result_pointer)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Extracts attributes of rd_kafka_DeleteAcls_result_response_t
70
+ #
71
+ # @private
72
+ class DeleteAclResult
73
+ attr_reader :result_error, :error_string, :matching_acls, :matching_acls_count
74
+
75
+ def initialize(acl_result_pointer)
76
+ @matching_acls=[]
77
+ rd_kafka_error_pointer = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_response_error(acl_result_pointer)
78
+ @result_error = Rdkafka::Bindings.rd_kafka_error_code(rd_kafka_error_pointer)
79
+ @error_string = Rdkafka::Bindings.rd_kafka_error_string(rd_kafka_error_pointer)
80
+ if @result_error == 0
81
+ # Get the number of matching acls
82
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
83
+ @matching_acls = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_response_matching_acls(acl_result_pointer, pointer_to_size_t)
84
+ @matching_acls_count = pointer_to_size_t.read_int
85
+ end
86
+ end
87
+
88
+ def self.delete_acl_results_from_array(count, array_pointer)
89
+ (1..count).map do |index|
90
+ result_pointer = (array_pointer + (index - 1)).read_pointer
91
+ new(result_pointer)
92
+ end
93
+ end
94
+ end
95
+
96
+ # Extracts attributes of rd_kafka_DeleteAcls_result_response_t
97
+ #
98
+ # @private
99
+ class DescribeAclResult
100
+ attr_reader :result_error, :error_string, :matching_acls, :matching_acls_count
101
+
102
+ def initialize(event_ptr)
103
+ @matching_acls=[]
104
+ @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
105
+ @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
106
+ if @result_error == 0
107
+ acl_describe_result = Rdkafka::Bindings.rd_kafka_event_DescribeAcls_result(event_ptr)
108
+ # Get the number of matching acls
109
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
110
+ @matching_acls = Rdkafka::Bindings.rd_kafka_DescribeAcls_result_acls(acl_describe_result, pointer_to_size_t)
111
+ @matching_acls_count = pointer_to_size_t.read_int
112
+ end
113
+ end
114
+ end
115
+
24
116
  # FFI Function used for Create Topic and Delete Topic callbacks
25
117
  BackgroundEventCallbackFunction = FFI::Function.new(
26
118
  :void, [:pointer, :pointer, :pointer]
@@ -36,6 +128,16 @@ module Rdkafka
36
128
  process_create_topic(event_ptr)
37
129
  elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT
38
130
  process_delete_topic(event_ptr)
131
+ elsif event_type == Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT
132
+ process_create_partitions(event_ptr)
133
+ elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT
134
+ process_create_acl(event_ptr)
135
+ elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT
136
+ process_delete_acl(event_ptr)
137
+ elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT
138
+ process_describe_acl(event_ptr)
139
+ elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT
140
+ process_delete_groups(event_ptr)
39
141
  end
40
142
  end
41
143
 
@@ -58,6 +160,23 @@ module Rdkafka
58
160
  end
59
161
  end
60
162
 
163
+ def self.process_delete_groups(event_ptr)
164
+ delete_groups_result = Rdkafka::Bindings.rd_kafka_event_DeleteGroups_result(event_ptr)
165
+
166
+ # Get the number of delete group results
167
+ pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
168
+ delete_group_result_array = Rdkafka::Bindings.rd_kafka_DeleteGroups_result_groups(delete_groups_result, pointer_to_size_t)
169
+ delete_group_results = GroupResult.create_group_results_from_array(pointer_to_size_t.read_int, delete_group_result_array) # TODO fix this
170
+ delete_group_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
171
+
172
+ if (delete_group_handle = Rdkafka::Admin::DeleteGroupsHandle.remove(delete_group_handle_ptr.address))
173
+ delete_group_handle[:response] = delete_group_results[0].result_error
174
+ delete_group_handle[:error_string] = delete_group_results[0].error_string
175
+ delete_group_handle[:result_name] = delete_group_results[0].result_name
176
+ delete_group_handle[:pending] = false
177
+ end
178
+ end
179
+
61
180
  def self.process_delete_topic(event_ptr)
62
181
  delete_topics_result = Rdkafka::Bindings.rd_kafka_event_DeleteTopics_result(event_ptr)
63
182
 
@@ -74,6 +193,74 @@ module Rdkafka
74
193
  delete_topic_handle[:pending] = false
75
194
  end
76
195
  end
196
+
197
+ def self.process_create_partitions(event_ptr)
198
+ create_partitionss_result = Rdkafka::Bindings.rd_kafka_event_CreatePartitions_result(event_ptr)
199
+
200
+ # Get the number of create topic results
201
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
202
+ create_partitions_result_array = Rdkafka::Bindings.rd_kafka_CreatePartitions_result_topics(create_partitionss_result, pointer_to_size_t)
203
+ create_partitions_results = TopicResult.create_topic_results_from_array(pointer_to_size_t.read_int, create_partitions_result_array)
204
+ create_partitions_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
205
+
206
+ if create_partitions_handle = Rdkafka::Admin::CreatePartitionsHandle.remove(create_partitions_handle_ptr.address)
207
+ create_partitions_handle[:response] = create_partitions_results[0].result_error
208
+ create_partitions_handle[:error_string] = create_partitions_results[0].error_string
209
+ create_partitions_handle[:result_name] = create_partitions_results[0].result_name
210
+ create_partitions_handle[:pending] = false
211
+ end
212
+ end
213
+
214
+ def self.process_create_acl(event_ptr)
215
+ create_acls_result = Rdkafka::Bindings.rd_kafka_event_CreateAcls_result(event_ptr)
216
+
217
+ # Get the number of acl results
218
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
219
+ create_acl_result_array = Rdkafka::Bindings.rd_kafka_CreateAcls_result_acls(create_acls_result, pointer_to_size_t)
220
+ create_acl_results = CreateAclResult.create_acl_results_from_array(pointer_to_size_t.read_int, create_acl_result_array)
221
+ create_acl_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
222
+
223
+ if create_acl_handle = Rdkafka::Admin::CreateAclHandle.remove(create_acl_handle_ptr.address)
224
+ create_acl_handle[:response] = create_acl_results[0].result_error
225
+ create_acl_handle[:response_string] = create_acl_results[0].error_string
226
+ create_acl_handle[:pending] = false
227
+ end
228
+ end
229
+
230
+ def self.process_delete_acl(event_ptr)
231
+ delete_acls_result = Rdkafka::Bindings.rd_kafka_event_DeleteAcls_result(event_ptr)
232
+
233
+ # Get the number of acl results
234
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
235
+ delete_acl_result_responses = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_responses(delete_acls_result, pointer_to_size_t)
236
+ delete_acl_results = DeleteAclResult.delete_acl_results_from_array(pointer_to_size_t.read_int, delete_acl_result_responses)
237
+ delete_acl_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
238
+
239
+ if delete_acl_handle = Rdkafka::Admin::DeleteAclHandle.remove(delete_acl_handle_ptr.address)
240
+ delete_acl_handle[:response] = delete_acl_results[0].result_error
241
+ delete_acl_handle[:response_string] = delete_acl_results[0].error_string
242
+ delete_acl_handle[:pending] = false
243
+ if delete_acl_results[0].result_error == 0
244
+ delete_acl_handle[:matching_acls] = delete_acl_results[0].matching_acls
245
+ delete_acl_handle[:matching_acls_count] = delete_acl_results[0].matching_acls_count
246
+ end
247
+ end
248
+ end
249
+
250
+ def self.process_describe_acl(event_ptr)
251
+ describe_acl = DescribeAclResult.new(event_ptr)
252
+ describe_acl_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
253
+
254
+ if describe_acl_handle = Rdkafka::Admin::DescribeAclHandle.remove(describe_acl_handle_ptr.address)
255
+ describe_acl_handle[:response] = describe_acl.result_error
256
+ describe_acl_handle[:response_string] = describe_acl.error_string
257
+ describe_acl_handle[:pending] = false
258
+ if describe_acl.result_error == 0
259
+ describe_acl_handle[:acls] = describe_acl.matching_acls
260
+ describe_acl_handle[:acls_count] = describe_acl.matching_acls_count
261
+ end
262
+ end
263
+ end
77
264
  end
78
265
 
79
266
  # FFI Function used for Message Delivery callbacks
@@ -90,17 +277,31 @@ module Rdkafka
90
277
  message = Rdkafka::Bindings::Message.new(message_ptr)
91
278
  delivery_handle_ptr_address = message[:_private].address
92
279
  if delivery_handle = Rdkafka::Producer::DeliveryHandle.remove(delivery_handle_ptr_address)
280
+ topic_name = Rdkafka::Bindings.rd_kafka_topic_name(message[:rkt])
281
+
93
282
  # Update delivery handle
94
283
  delivery_handle[:response] = message[:err]
95
284
  delivery_handle[:partition] = message[:partition]
96
285
  delivery_handle[:offset] = message[:offset]
286
+ delivery_handle[:topic_name] = FFI::MemoryPointer.from_string(topic_name)
97
287
  delivery_handle[:pending] = false
288
+
98
289
  # Call delivery callback on opaque
99
290
  if opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
100
- opaque.call_delivery_callback(Rdkafka::Producer::DeliveryReport.new(message[:partition], message[:offset], message[:err]), delivery_handle)
291
+ opaque.call_delivery_callback(
292
+ Rdkafka::Producer::DeliveryReport.new(
293
+ message[:partition],
294
+ message[:offset],
295
+ topic_name,
296
+ message[:err],
297
+ delivery_handle.label
298
+ ),
299
+ delivery_handle
300
+ )
101
301
  end
102
302
  end
103
303
  end
104
304
  end
305
+
105
306
  end
106
307
  end