rdkafka 0.28.0-aarch64-linux-gnu → 0.29.1-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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +3 -2
- data/bin/verify_kafka_warnings +5 -0
- data/docker-compose-ssl.yml +4 -1
- data/docker-compose.yml +4 -1
- data/ext/librdkafka.so +0 -0
- data/lib/rdkafka/abstract_handle.rb +31 -2
- data/lib/rdkafka/admin/config_binding_result.rb +2 -2
- data/lib/rdkafka/admin/create_acl_handle.rb +6 -5
- data/lib/rdkafka/admin/create_acl_report.rb +2 -1
- data/lib/rdkafka/admin/create_partitions_handle.rb +4 -6
- data/lib/rdkafka/admin/create_topic_handle.rb +4 -6
- data/lib/rdkafka/admin/delete_acl_handle.rb +5 -7
- data/lib/rdkafka/admin/delete_groups_handle.rb +4 -6
- data/lib/rdkafka/admin/delete_records_handle.rb +31 -0
- data/lib/rdkafka/admin/delete_records_report.rb +25 -0
- data/lib/rdkafka/admin/delete_topic_handle.rb +4 -6
- data/lib/rdkafka/admin/describe_acl_handle.rb +5 -7
- data/lib/rdkafka/admin/describe_acl_report.rb +2 -1
- data/lib/rdkafka/admin/describe_configs_handle.rb +4 -10
- data/lib/rdkafka/admin/describe_configs_report.rb +1 -5
- data/lib/rdkafka/admin/incremental_alter_configs_handle.rb +4 -10
- data/lib/rdkafka/admin/incremental_alter_configs_report.rb +1 -5
- data/lib/rdkafka/admin/list_consumer_groups_handle.rb +31 -0
- data/lib/rdkafka/admin/list_consumer_groups_report.rb +83 -0
- data/lib/rdkafka/admin/list_offsets_handle.rb +5 -10
- data/lib/rdkafka/admin/list_offsets_report.rb +5 -2
- data/lib/rdkafka/admin.rb +238 -145
- data/lib/rdkafka/bindings.rb +61 -16
- data/lib/rdkafka/callbacks/base_handler.rb +62 -0
- data/lib/rdkafka/callbacks/create_acl_handler.rb +37 -0
- data/lib/rdkafka/callbacks/create_partitions_handler.rb +37 -0
- data/lib/rdkafka/callbacks/create_topic_handler.rb +37 -0
- data/lib/rdkafka/callbacks/delete_acl_handler.rb +42 -0
- data/lib/rdkafka/callbacks/delete_groups_handler.rb +37 -0
- data/lib/rdkafka/callbacks/delete_records_handler.rb +38 -0
- data/lib/rdkafka/callbacks/delete_topic_handler.rb +37 -0
- data/lib/rdkafka/callbacks/describe_acl_handler.rb +35 -0
- data/lib/rdkafka/callbacks/describe_configs_handler.rb +42 -0
- data/lib/rdkafka/callbacks/incremental_alter_configs_handler.rb +42 -0
- data/lib/rdkafka/callbacks/list_consumer_groups_handler.rb +39 -0
- data/lib/rdkafka/callbacks/list_offsets_handler.rb +42 -0
- data/lib/rdkafka/callbacks.rb +54 -246
- data/lib/rdkafka/config.rb +69 -50
- data/lib/rdkafka/consumer/headers.rb +19 -5
- data/lib/rdkafka/consumer/partition.rb +8 -1
- data/lib/rdkafka/consumer/topic_partition_list.rb +58 -30
- data/lib/rdkafka/consumer.rb +211 -52
- data/lib/rdkafka/defaults.rb +24 -7
- data/lib/rdkafka/helpers/list_offsets.rb +127 -0
- data/lib/rdkafka/helpers/metadata.rb +29 -0
- data/lib/rdkafka/helpers/oauth.rb +10 -5
- data/lib/rdkafka/metadata.rb +86 -19
- data/lib/rdkafka/native_kafka.rb +22 -11
- data/lib/rdkafka/producer/delivery_handle.rb +4 -5
- data/lib/rdkafka/producer/partitions_count_cache.rb +24 -38
- data/lib/rdkafka/producer.rb +81 -61
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +19 -0
- data/package-lock.json +3 -3
- data/rdkafka.gemspec +1 -0
- metadata +21 -5
- data/Gemfile +0 -13
- data/Gemfile.lint +0 -14
- data/Gemfile.lint.lock +0 -123
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_LISTOFFSETS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class ListOffsetsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the list-offsets handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
list_offsets = ListOffsetsResult.new(event_ptr)
|
|
14
|
+
list_offsets_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
if list_offsets_handle = Rdkafka::Admin::ListOffsetsHandle.remove(list_offsets_handle_ptr.address)
|
|
17
|
+
list_offsets_handle[:response] = list_offsets.result_error
|
|
18
|
+
list_offsets_handle.broker_message = read_event_string(list_offsets.error_string)
|
|
19
|
+
|
|
20
|
+
# Parsing can raise on per-partition errors. The exception is captured and re-raised
|
|
21
|
+
# on the waiting thread, since an exception leaving this callback would unwind through
|
|
22
|
+
# librdkafka native frames.
|
|
23
|
+
list_offsets_handle.result = begin
|
|
24
|
+
if list_offsets.result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
25
|
+
Rdkafka::Admin::ListOffsetsReport.new(
|
|
26
|
+
result_infos: list_offsets.result_infos,
|
|
27
|
+
result_count: list_offsets.result_count
|
|
28
|
+
)
|
|
29
|
+
else
|
|
30
|
+
Rdkafka::Admin::ListOffsetsReport.new(result_infos: FFI::Pointer::NULL, result_count: 0)
|
|
31
|
+
end
|
|
32
|
+
rescue => e
|
|
33
|
+
e
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
list_offsets_handle.unlock
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/rdkafka/callbacks.rb
CHANGED
|
@@ -98,7 +98,7 @@ module Rdkafka
|
|
|
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
100
|
# Get the number of matching acls
|
|
101
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:
|
|
101
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
102
102
|
@matching_acls = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_response_matching_acls(acl_result_pointer, pointer_to_size_t)
|
|
103
103
|
@matching_acls_count = pointer_to_size_t.read_int
|
|
104
104
|
end
|
|
@@ -129,7 +129,7 @@ module Rdkafka
|
|
|
129
129
|
if @result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
130
130
|
acl_describe_result = Rdkafka::Bindings.rd_kafka_event_DescribeAcls_result(event_ptr)
|
|
131
131
|
# Get the number of matching acls
|
|
132
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:
|
|
132
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
133
133
|
@matching_acls = Rdkafka::Bindings.rd_kafka_DescribeAcls_result_acls(acl_describe_result, pointer_to_size_t)
|
|
134
134
|
@matching_acls_count = pointer_to_size_t.read_int
|
|
135
135
|
end
|
|
@@ -151,7 +151,7 @@ module Rdkafka
|
|
|
151
151
|
if @result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
152
152
|
configs_describe_result = Rdkafka::Bindings.rd_kafka_event_DescribeConfigs_result(event_ptr)
|
|
153
153
|
# Get the number of matching acls
|
|
154
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:
|
|
154
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
155
155
|
@results = Rdkafka::Bindings.rd_kafka_DescribeConfigs_result_resources(configs_describe_result, pointer_to_size_t)
|
|
156
156
|
@results_count = pointer_to_size_t.read_int
|
|
157
157
|
end
|
|
@@ -173,7 +173,7 @@ module Rdkafka
|
|
|
173
173
|
if @result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
174
174
|
incremental_alter_result = Rdkafka::Bindings.rd_kafka_event_IncrementalAlterConfigs_result(event_ptr)
|
|
175
175
|
# Get the number of matching acls
|
|
176
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:
|
|
176
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
177
177
|
@results = Rdkafka::Bindings.rd_kafka_IncrementalAlterConfigs_result_resources(incremental_alter_result, pointer_to_size_t)
|
|
178
178
|
@results_count = pointer_to_size_t.read_int
|
|
179
179
|
end
|
|
@@ -208,232 +208,28 @@ module Rdkafka
|
|
|
208
208
|
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
209
209
|
# @param _opaque_ptr [FFI::Pointer] unused opaque pointer
|
|
210
210
|
def self.call(_client_ptr, event_ptr, _opaque_ptr)
|
|
211
|
-
case Rdkafka::Bindings.rd_kafka_event_type(event_ptr)
|
|
212
|
-
when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATETOPICS_RESULT
|
|
213
|
-
|
|
214
|
-
when Rdkafka::Bindings::
|
|
215
|
-
|
|
216
|
-
when Rdkafka::Bindings::
|
|
217
|
-
|
|
218
|
-
when Rdkafka::Bindings::
|
|
219
|
-
|
|
220
|
-
when Rdkafka::Bindings::
|
|
221
|
-
|
|
222
|
-
when Rdkafka::Bindings::
|
|
223
|
-
|
|
224
|
-
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT
|
|
225
|
-
process_delete_acl(event_ptr)
|
|
226
|
-
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT
|
|
227
|
-
process_describe_acl(event_ptr)
|
|
228
|
-
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT
|
|
229
|
-
process_delete_groups(event_ptr)
|
|
230
|
-
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTOFFSETS_RESULT
|
|
231
|
-
process_list_offsets(event_ptr)
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
private
|
|
236
|
-
|
|
237
|
-
# Processes create topic result event
|
|
238
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
239
|
-
def self.process_create_topic(event_ptr)
|
|
240
|
-
create_topics_result = Rdkafka::Bindings.rd_kafka_event_CreateTopics_result(event_ptr)
|
|
241
|
-
|
|
242
|
-
# Get the number of create topic results
|
|
243
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:int32)
|
|
244
|
-
create_topic_result_array = Rdkafka::Bindings.rd_kafka_CreateTopics_result_topics(create_topics_result, pointer_to_size_t)
|
|
245
|
-
create_topic_results = TopicResult.create_topic_results_from_array(pointer_to_size_t.read_int, create_topic_result_array)
|
|
246
|
-
create_topic_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
247
|
-
|
|
248
|
-
if create_topic_handle = Rdkafka::Admin::CreateTopicHandle.remove(create_topic_handle_ptr.address)
|
|
249
|
-
create_topic_handle[:response] = create_topic_results[0].result_error
|
|
250
|
-
create_topic_handle[:error_string] = create_topic_results[0].error_string
|
|
251
|
-
create_topic_handle[:result_name] = create_topic_results[0].result_name
|
|
252
|
-
|
|
253
|
-
create_topic_handle.unlock
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
# Processes describe configs result event
|
|
258
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
259
|
-
def self.process_describe_configs(event_ptr)
|
|
260
|
-
describe_configs = DescribeConfigsResult.new(event_ptr)
|
|
261
|
-
describe_configs_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
262
|
-
|
|
263
|
-
if describe_configs_handle = Rdkafka::Admin::DescribeConfigsHandle.remove(describe_configs_handle_ptr.address)
|
|
264
|
-
describe_configs_handle[:response] = describe_configs.result_error
|
|
265
|
-
describe_configs_handle[:response_string] = describe_configs.error_string
|
|
266
|
-
describe_configs_handle[:pending] = false
|
|
267
|
-
|
|
268
|
-
if describe_configs.result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
269
|
-
describe_configs_handle[:config_entries] = describe_configs.results
|
|
270
|
-
describe_configs_handle[:entry_count] = describe_configs.results_count
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
describe_configs_handle.unlock
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
# Processes incremental alter configs result event
|
|
278
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
279
|
-
def self.process_incremental_alter_configs(event_ptr)
|
|
280
|
-
incremental_alter = IncrementalAlterConfigsResult.new(event_ptr)
|
|
281
|
-
incremental_alter_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
282
|
-
|
|
283
|
-
if incremental_alter_handle = Rdkafka::Admin::IncrementalAlterConfigsHandle.remove(incremental_alter_handle_ptr.address)
|
|
284
|
-
incremental_alter_handle[:response] = incremental_alter.result_error
|
|
285
|
-
incremental_alter_handle[:response_string] = incremental_alter.error_string
|
|
286
|
-
incremental_alter_handle[:pending] = false
|
|
287
|
-
|
|
288
|
-
if incremental_alter.result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
289
|
-
incremental_alter_handle[:config_entries] = incremental_alter.results
|
|
290
|
-
incremental_alter_handle[:entry_count] = incremental_alter.results_count
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
incremental_alter_handle.unlock
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
# Processes delete groups result event
|
|
298
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
299
|
-
def self.process_delete_groups(event_ptr)
|
|
300
|
-
delete_groups_result = Rdkafka::Bindings.rd_kafka_event_DeleteGroups_result(event_ptr)
|
|
301
|
-
|
|
302
|
-
# Get the number of delete group results
|
|
303
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
304
|
-
delete_group_result_array = Rdkafka::Bindings.rd_kafka_DeleteGroups_result_groups(delete_groups_result, pointer_to_size_t)
|
|
305
|
-
delete_group_results = GroupResult.create_group_results_from_array(pointer_to_size_t.read_int, delete_group_result_array) # TODO fix this
|
|
306
|
-
delete_group_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
307
|
-
|
|
308
|
-
if (delete_group_handle = Rdkafka::Admin::DeleteGroupsHandle.remove(delete_group_handle_ptr.address))
|
|
309
|
-
delete_group_handle[:response] = delete_group_results[0].result_error
|
|
310
|
-
delete_group_handle[:error_string] = delete_group_results[0].error_string
|
|
311
|
-
delete_group_handle[:result_name] = delete_group_results[0].result_name
|
|
312
|
-
|
|
313
|
-
delete_group_handle.unlock
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
# Processes delete topic result event
|
|
318
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
319
|
-
def self.process_delete_topic(event_ptr)
|
|
320
|
-
delete_topics_result = Rdkafka::Bindings.rd_kafka_event_DeleteTopics_result(event_ptr)
|
|
321
|
-
|
|
322
|
-
# Get the number of topic results
|
|
323
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:int32)
|
|
324
|
-
delete_topic_result_array = Rdkafka::Bindings.rd_kafka_DeleteTopics_result_topics(delete_topics_result, pointer_to_size_t)
|
|
325
|
-
delete_topic_results = TopicResult.create_topic_results_from_array(pointer_to_size_t.read_int, delete_topic_result_array)
|
|
326
|
-
delete_topic_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
327
|
-
|
|
328
|
-
if delete_topic_handle = Rdkafka::Admin::DeleteTopicHandle.remove(delete_topic_handle_ptr.address)
|
|
329
|
-
delete_topic_handle[:response] = delete_topic_results[0].result_error
|
|
330
|
-
delete_topic_handle[:error_string] = delete_topic_results[0].error_string
|
|
331
|
-
delete_topic_handle[:result_name] = delete_topic_results[0].result_name
|
|
332
|
-
|
|
333
|
-
delete_topic_handle.unlock
|
|
211
|
+
handler = case Rdkafka::Bindings.rd_kafka_event_type(event_ptr)
|
|
212
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATETOPICS_RESULT then CreateTopicHandler
|
|
213
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT then DeleteTopicHandler
|
|
214
|
+
when Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT then CreatePartitionsHandler
|
|
215
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT then DeleteGroupsHandler
|
|
216
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETERECORDS_RESULT then DeleteRecordsHandler
|
|
217
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT then CreateAclHandler
|
|
218
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT then DeleteAclHandler
|
|
219
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT then DescribeAclHandler
|
|
220
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBECONFIGS_RESULT then DescribeConfigsHandler
|
|
221
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT then IncrementalAlterConfigsHandler
|
|
222
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTOFFSETS_RESULT then ListOffsetsHandler
|
|
223
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT then ListConsumerGroupsHandler
|
|
334
224
|
end
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
# Processes create partitions result event
|
|
338
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
339
|
-
def self.process_create_partitions(event_ptr)
|
|
340
|
-
create_partitionss_result = Rdkafka::Bindings.rd_kafka_event_CreatePartitions_result(event_ptr)
|
|
341
|
-
|
|
342
|
-
# Get the number of create topic results
|
|
343
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:int32)
|
|
344
|
-
create_partitions_result_array = Rdkafka::Bindings.rd_kafka_CreatePartitions_result_topics(create_partitionss_result, pointer_to_size_t)
|
|
345
|
-
create_partitions_results = TopicResult.create_topic_results_from_array(pointer_to_size_t.read_int, create_partitions_result_array)
|
|
346
|
-
create_partitions_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
347
225
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
# Processes create ACL result event
|
|
358
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
359
|
-
def self.process_create_acl(event_ptr)
|
|
360
|
-
create_acls_result = Rdkafka::Bindings.rd_kafka_event_CreateAcls_result(event_ptr)
|
|
361
|
-
|
|
362
|
-
# Get the number of acl results
|
|
363
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:int32)
|
|
364
|
-
create_acl_result_array = Rdkafka::Bindings.rd_kafka_CreateAcls_result_acls(create_acls_result, pointer_to_size_t)
|
|
365
|
-
create_acl_results = CreateAclResult.create_acl_results_from_array(pointer_to_size_t.read_int, create_acl_result_array)
|
|
366
|
-
create_acl_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
367
|
-
|
|
368
|
-
if create_acl_handle = Rdkafka::Admin::CreateAclHandle.remove(create_acl_handle_ptr.address)
|
|
369
|
-
create_acl_handle[:response] = create_acl_results[0].result_error
|
|
370
|
-
create_acl_handle[:response_string] = create_acl_results[0].error_string
|
|
371
|
-
|
|
372
|
-
create_acl_handle.unlock
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
# Processes delete ACL result event
|
|
377
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
378
|
-
def self.process_delete_acl(event_ptr)
|
|
379
|
-
delete_acls_result = Rdkafka::Bindings.rd_kafka_event_DeleteAcls_result(event_ptr)
|
|
380
|
-
|
|
381
|
-
# Get the number of acl results
|
|
382
|
-
pointer_to_size_t = FFI::MemoryPointer.new(:int32)
|
|
383
|
-
delete_acl_result_responses = Rdkafka::Bindings.rd_kafka_DeleteAcls_result_responses(delete_acls_result, pointer_to_size_t)
|
|
384
|
-
delete_acl_results = DeleteAclResult.delete_acl_results_from_array(pointer_to_size_t.read_int, delete_acl_result_responses)
|
|
385
|
-
delete_acl_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
386
|
-
|
|
387
|
-
if delete_acl_handle = Rdkafka::Admin::DeleteAclHandle.remove(delete_acl_handle_ptr.address)
|
|
388
|
-
delete_acl_handle[:response] = delete_acl_results[0].result_error
|
|
389
|
-
delete_acl_handle[:response_string] = delete_acl_results[0].error_string
|
|
390
|
-
|
|
391
|
-
if delete_acl_results[0].result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
392
|
-
delete_acl_handle[:matching_acls] = delete_acl_results[0].matching_acls
|
|
393
|
-
delete_acl_handle[:matching_acls_count] = delete_acl_results[0].matching_acls_count
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
delete_acl_handle.unlock
|
|
397
|
-
end
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
# Processes describe ACL result event
|
|
401
|
-
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
402
|
-
def self.process_describe_acl(event_ptr)
|
|
403
|
-
describe_acl = DescribeAclResult.new(event_ptr)
|
|
404
|
-
describe_acl_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
405
|
-
|
|
406
|
-
if describe_acl_handle = Rdkafka::Admin::DescribeAclHandle.remove(describe_acl_handle_ptr.address)
|
|
407
|
-
describe_acl_handle[:response] = describe_acl.result_error
|
|
408
|
-
describe_acl_handle[:response_string] = describe_acl.error_string
|
|
409
|
-
|
|
410
|
-
if describe_acl.result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
411
|
-
describe_acl_handle[:acls] = describe_acl.matching_acls
|
|
412
|
-
describe_acl_handle[:acls_count] = describe_acl.matching_acls_count
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
describe_acl_handle.unlock
|
|
416
|
-
end
|
|
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
|
|
226
|
+
handler&.call(event_ptr)
|
|
227
|
+
ensure
|
|
228
|
+
# Background queue events are owned by the application and must be destroyed once
|
|
229
|
+
# served (see rd_kafka_conf_set_background_event_cb). All event-owned memory (result
|
|
230
|
+
# arrays, strings) has to be copied into Ruby objects by the handlers above before this
|
|
231
|
+
# runs - nothing may retain pointers into the event past this point.
|
|
232
|
+
Rdkafka::Bindings.rd_kafka_event_destroy(event_ptr)
|
|
437
233
|
end
|
|
438
234
|
end
|
|
439
235
|
|
|
@@ -453,30 +249,42 @@ module Rdkafka
|
|
|
453
249
|
delivery_handle[:response] = message[:err]
|
|
454
250
|
delivery_handle[:partition] = message[:partition]
|
|
455
251
|
delivery_handle[:offset] = message[:offset]
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
#
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
252
|
+
# The topic is not stored on the handle here: it is already set as the handle's
|
|
253
|
+
# `topic` Ruby attribute during produce, which spares a native string copy that
|
|
254
|
+
# would otherwise be allocated and retained for every message.
|
|
255
|
+
|
|
256
|
+
begin
|
|
257
|
+
# Call delivery callback on opaque
|
|
258
|
+
if opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
|
|
259
|
+
opaque.call_delivery_callback(
|
|
260
|
+
Rdkafka::Producer::DeliveryReport.new(
|
|
261
|
+
message[:partition],
|
|
262
|
+
message[:offset],
|
|
263
|
+
topic_name,
|
|
264
|
+
message[:err],
|
|
265
|
+
delivery_handle.label
|
|
266
|
+
),
|
|
267
|
+
delivery_handle
|
|
268
|
+
)
|
|
269
|
+
end
|
|
270
|
+
rescue Exception => err
|
|
271
|
+
# A user delivery callback that raises must not escape this FFI callback: it runs on
|
|
272
|
+
# librdkafka's polling thread (abort_on_exception = true), so an escaping exception
|
|
273
|
+
# would crash the whole process. We log and swallow it, matching the rebalance
|
|
274
|
+
# callback. The `ensure` below still unlocks the handle, so `wait` returns the
|
|
275
|
+
# delivery report instead of blocking until its timeout and raising
|
|
276
|
+
# WaitTimeoutError for a message that was in fact delivered.
|
|
277
|
+
Rdkafka::Config.logger.error("Unhandled exception: #{err.class} - #{err.message}")
|
|
278
|
+
ensure
|
|
279
|
+
delivery_handle.unlock
|
|
470
280
|
end
|
|
471
|
-
|
|
472
|
-
delivery_handle.unlock
|
|
473
281
|
end
|
|
474
282
|
end
|
|
475
283
|
end
|
|
476
284
|
|
|
477
|
-
#
|
|
285
|
+
# @!visibility private
|
|
478
286
|
@@mutex = Mutex.new
|
|
479
|
-
#
|
|
287
|
+
# @!visibility private
|
|
480
288
|
@@current_pid = nil
|
|
481
289
|
|
|
482
290
|
class << self
|
data/lib/rdkafka/config.rb
CHANGED
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
module Rdkafka
|
|
4
4
|
# Configuration for a Kafka consumer or producer. You can create an instance and use
|
|
5
5
|
# the consumer and producer methods to create a client. Documentation of the available
|
|
6
|
-
# configuration options is available on
|
|
6
|
+
# configuration options is available on
|
|
7
|
+
# https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md.
|
|
7
8
|
class Config
|
|
8
|
-
#
|
|
9
|
+
# @!visibility private
|
|
9
10
|
@@logger = Logger.new($stdout)
|
|
10
|
-
#
|
|
11
|
+
# @!visibility private
|
|
11
12
|
@@statistics_callback = nil
|
|
12
|
-
#
|
|
13
|
+
# @!visibility private
|
|
13
14
|
@@error_callback = nil
|
|
14
|
-
#
|
|
15
|
+
# @!visibility private
|
|
15
16
|
@@opaques = ObjectSpace::WeakMap.new
|
|
16
|
-
#
|
|
17
|
+
# @!visibility private
|
|
17
18
|
@@log_queue = Queue.new
|
|
18
|
-
# We memoize thread on
|
|
19
|
-
# This allows us also to restart logger thread on forks
|
|
19
|
+
# We memoize thread on first log flush. This allows us also to restart logger thread on forks
|
|
20
20
|
@@log_thread = nil
|
|
21
|
-
#
|
|
21
|
+
# @!visibility private
|
|
22
22
|
@@log_mutex = Mutex.new
|
|
23
|
-
#
|
|
23
|
+
# @!visibility private
|
|
24
24
|
@@oauthbearer_token_refresh_callback = nil
|
|
25
25
|
|
|
26
26
|
# Returns the current logger, by default this is a logger to stdout.
|
|
@@ -69,7 +69,8 @@ module Rdkafka
|
|
|
69
69
|
|
|
70
70
|
# Set a callback that will be called every time the underlying client emits statistics.
|
|
71
71
|
# You can configure if and how often this happens using `statistics.interval.ms`.
|
|
72
|
-
# The callback is called with a hash that's documented here:
|
|
72
|
+
# The callback is called with a hash that's documented here:
|
|
73
|
+
# https://github.com/confluentinc/librdkafka/blob/master/STATISTICS.md
|
|
73
74
|
#
|
|
74
75
|
# @param callback [Proc, #call, nil] callable object or nil to clear
|
|
75
76
|
# @return [nil]
|
|
@@ -86,7 +87,8 @@ module Rdkafka
|
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
# Set a callback that will be called every time the underlying client emits an error.
|
|
89
|
-
# If this callback is not set, global errors such as brokers becoming unavailable will only be
|
|
90
|
+
# If this callback is not set, global errors such as brokers becoming unavailable will only be
|
|
91
|
+
# sent to the logger, as defined by librdkafka.
|
|
90
92
|
# The callback is called with an instance of RdKafka::Error.
|
|
91
93
|
#
|
|
92
94
|
# @param callback [Proc, #call, nil] callable object to handle errors or nil to clear
|
|
@@ -197,6 +199,11 @@ module Rdkafka
|
|
|
197
199
|
opaque = Opaque.new
|
|
198
200
|
config = native_config(opaque)
|
|
199
201
|
|
|
202
|
+
# Set callback to receive background events, so admin-style operations issued on the
|
|
203
|
+
# consumer handle (e.g. Consumer#list_offsets) get their results dispatched back to their
|
|
204
|
+
# handles. librdkafka spawns its internally-managed background thread because of this.
|
|
205
|
+
Rdkafka::Bindings.rd_kafka_conf_set_background_event_cb(config, Rdkafka::Callbacks::BackgroundEventCallbackFunction)
|
|
206
|
+
|
|
200
207
|
if @consumer_rebalance_listener
|
|
201
208
|
opaque.consumer_rebalance_listener = @consumer_rebalance_listener
|
|
202
209
|
Rdkafka::Bindings.rd_kafka_conf_set_rebalance_cb(config, Rdkafka::Bindings::RebalanceCallback)
|
|
@@ -290,6 +297,9 @@ module Rdkafka
|
|
|
290
297
|
# Uses `rd_kafka_conf_dump` to retrieve every property (including defaults and
|
|
291
298
|
# internal properties like `client.software.name`) as a flat Hash.
|
|
292
299
|
#
|
|
300
|
+
# @return [Hash{Symbol => String}] property names mapped to their current values
|
|
301
|
+
#
|
|
302
|
+
# @raise [ConfigError] When the configuration contains invalid options
|
|
293
303
|
# @note The librdkafka C API does not distinguish between producer-only, consumer-only,
|
|
294
304
|
# and global properties at the configuration level. All properties are returned
|
|
295
305
|
# regardless of the intended client type.
|
|
@@ -297,10 +307,6 @@ module Rdkafka
|
|
|
297
307
|
# @note The returned Hash may include sensitive values such as authentication
|
|
298
308
|
# credentials and key passwords. Do not log or serialize the returned data
|
|
299
309
|
# unless you have explicitly redacted secret entries.
|
|
300
|
-
#
|
|
301
|
-
# @return [Hash{Symbol => String}] property names mapped to their current values
|
|
302
|
-
#
|
|
303
|
-
# @raise [ConfigError] When the configuration contains invalid options
|
|
304
310
|
def describe_properties
|
|
305
311
|
config = nil
|
|
306
312
|
dump_ptr = nil
|
|
@@ -325,7 +331,8 @@ module Rdkafka
|
|
|
325
331
|
Rdkafka::Bindings.rd_kafka_conf_destroy(config) if config
|
|
326
332
|
end
|
|
327
333
|
|
|
328
|
-
# Error that is returned by the underlying rdkafka error if an invalid configuration option is
|
|
334
|
+
# Error that is returned by the underlying rdkafka error if an invalid configuration option is
|
|
335
|
+
# present.
|
|
329
336
|
class ConfigError < RuntimeError; end
|
|
330
337
|
|
|
331
338
|
# Error that is returned by the underlying rdkafka library if the client cannot be created.
|
|
@@ -342,47 +349,55 @@ module Rdkafka
|
|
|
342
349
|
# @param opaque [Object, nil] optional opaque pointer for callbacks
|
|
343
350
|
# @return [FFI::Pointer] native rdkafka configuration pointer
|
|
344
351
|
def native_config(opaque = nil)
|
|
345
|
-
Rdkafka::Bindings.rd_kafka_conf_new
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
352
|
+
config = Rdkafka::Bindings.rd_kafka_conf_new
|
|
353
|
+
|
|
354
|
+
# Create config
|
|
355
|
+
@config_hash.merge(REQUIRED_CONFIG).each do |key, value|
|
|
356
|
+
error_buffer = FFI::MemoryPointer.from_string(" " * 256)
|
|
357
|
+
result = Rdkafka::Bindings.rd_kafka_conf_set(
|
|
358
|
+
config,
|
|
359
|
+
key.to_s,
|
|
360
|
+
value.to_s,
|
|
361
|
+
error_buffer,
|
|
362
|
+
256
|
|
363
|
+
)
|
|
364
|
+
unless result == :config_ok
|
|
365
|
+
raise ConfigError.new(error_buffer.read_string)
|
|
359
366
|
end
|
|
367
|
+
end
|
|
360
368
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
# Set opaque pointer that's used as a proxy for callbacks
|
|
370
|
+
if opaque
|
|
371
|
+
pointer = ::FFI::Pointer.new(:pointer, opaque.object_id)
|
|
372
|
+
Rdkafka::Bindings.rd_kafka_conf_set_opaque(config, pointer)
|
|
365
373
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
374
|
+
# Store opaque with the pointer as key. We use this approach instead
|
|
375
|
+
# of trying to convert the pointer to a Ruby object because there is
|
|
376
|
+
# no risk of a segfault this way.
|
|
377
|
+
Rdkafka::Config.opaques[pointer.to_i] = opaque
|
|
378
|
+
end
|
|
371
379
|
|
|
372
|
-
|
|
373
|
-
|
|
380
|
+
# Set log callback
|
|
381
|
+
Rdkafka::Bindings.rd_kafka_conf_set_log_cb(config, Rdkafka::Bindings::LogCallback)
|
|
374
382
|
|
|
375
|
-
|
|
376
|
-
|
|
383
|
+
# Set stats callback
|
|
384
|
+
Rdkafka::Bindings.rd_kafka_conf_set_stats_cb(config, Rdkafka::Bindings::StatsCallback)
|
|
377
385
|
|
|
378
|
-
|
|
379
|
-
|
|
386
|
+
# Set error callback
|
|
387
|
+
Rdkafka::Bindings.rd_kafka_conf_set_error_cb(config, Rdkafka::Bindings::ErrorCallback)
|
|
380
388
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
end
|
|
389
|
+
# Set oauth callback
|
|
390
|
+
if Rdkafka::Config.oauthbearer_token_refresh_callback
|
|
391
|
+
Rdkafka::Bindings.rd_kafka_conf_set_oauthbearer_token_refresh_cb(config, Rdkafka::Bindings::OAuthbearerTokenRefreshCallback)
|
|
385
392
|
end
|
|
393
|
+
|
|
394
|
+
config
|
|
395
|
+
rescue Exception
|
|
396
|
+
# rd_kafka_conf_new allocates a conf the caller owns until it is handed to rd_kafka_new. If
|
|
397
|
+
# we raise before returning it (e.g. an invalid option in the loop above), destroy it here
|
|
398
|
+
# so the native config is not leaked.
|
|
399
|
+
Rdkafka::Bindings.rd_kafka_conf_destroy(config) if config
|
|
400
|
+
raise
|
|
386
401
|
end
|
|
387
402
|
|
|
388
403
|
# Creates a native Kafka handle
|
|
@@ -400,6 +415,10 @@ module Rdkafka
|
|
|
400
415
|
)
|
|
401
416
|
|
|
402
417
|
if handle.null?
|
|
418
|
+
# On success rd_kafka_new takes ownership of the conf and frees it itself; on failure
|
|
419
|
+
# librdkafka keeps application ownership (see rdkafka.c), so we must destroy it here to
|
|
420
|
+
# avoid leaking the conf on every failed client creation.
|
|
421
|
+
Rdkafka::Bindings.rd_kafka_conf_destroy(config)
|
|
403
422
|
raise ClientCreationError.new(error_buffer.read_string)
|
|
404
423
|
end
|
|
405
424
|
|
|
@@ -7,6 +7,11 @@ module Rdkafka
|
|
|
7
7
|
# Empty frozen hash used when there are no headers
|
|
8
8
|
EMPTY_HEADERS = {}.freeze
|
|
9
9
|
|
|
10
|
+
# Key under which reusable scratch pointers are stored on the current thread/fiber
|
|
11
|
+
SCRATCH_KEY = :rdkafka_headers_scratch
|
|
12
|
+
|
|
13
|
+
private_constant :SCRATCH_KEY
|
|
14
|
+
|
|
10
15
|
# Reads a librdkafka native message's headers and returns them as a Ruby Hash
|
|
11
16
|
# where each key maps to either a String (single value) or Array<String> (multiple values)
|
|
12
17
|
# to support duplicate headers per KIP-82
|
|
@@ -17,7 +22,20 @@ module Rdkafka
|
|
|
17
22
|
# @return [Hash{String => String, Array<String>}] headers Hash for the native_message
|
|
18
23
|
# @raise [Rdkafka::RdkafkaError] when fail to read headers
|
|
19
24
|
def self.from_native(native_message)
|
|
20
|
-
|
|
25
|
+
# Scratch output pointers for the header FFI calls, reused across messages. They are
|
|
26
|
+
# stored in fiber-local storage (`Thread.current[]` is fiber-local by design), so each
|
|
27
|
+
# thread and each fiber gets its own set and reuse is safe with fiber schedulers. They
|
|
28
|
+
# never escape this method and all data is read out of them before returning.
|
|
29
|
+
# Allocating them per message would cost several native allocations for every consumed
|
|
30
|
+
# message.
|
|
31
|
+
headers_ptrptr, name_ptrptr, value_ptrptr, size_ptr =
|
|
32
|
+
Thread.current[SCRATCH_KEY] ||= [
|
|
33
|
+
FFI::MemoryPointer.new(:pointer),
|
|
34
|
+
FFI::MemoryPointer.new(:pointer),
|
|
35
|
+
FFI::MemoryPointer.new(:pointer),
|
|
36
|
+
Rdkafka::Bindings::SizePtr.new
|
|
37
|
+
].freeze
|
|
38
|
+
|
|
21
39
|
err = Rdkafka::Bindings.rd_kafka_message_headers(native_message, headers_ptrptr)
|
|
22
40
|
|
|
23
41
|
if err == Rdkafka::Bindings::RD_KAFKA_RESP_ERR__NOENT
|
|
@@ -28,10 +46,6 @@ module Rdkafka
|
|
|
28
46
|
|
|
29
47
|
headers_ptr = headers_ptrptr.read_pointer
|
|
30
48
|
|
|
31
|
-
name_ptrptr = FFI::MemoryPointer.new(:pointer)
|
|
32
|
-
value_ptrptr = FFI::MemoryPointer.new(:pointer)
|
|
33
|
-
size_ptr = Rdkafka::Bindings::SizePtr.new
|
|
34
|
-
|
|
35
49
|
headers = {}
|
|
36
50
|
|
|
37
51
|
idx = 0
|
|
@@ -16,14 +16,20 @@ module Rdkafka
|
|
|
16
16
|
# @return [Integer]
|
|
17
17
|
attr_reader :err
|
|
18
18
|
|
|
19
|
+
# Partition metadata in the context of a consumer
|
|
20
|
+
# @return [String, nil]
|
|
21
|
+
attr_reader :metadata
|
|
22
|
+
|
|
19
23
|
# @private
|
|
20
24
|
# @param partition [Integer] partition number
|
|
21
25
|
# @param offset [Integer, nil] partition offset
|
|
22
26
|
# @param err [Integer] error code from librdkafka
|
|
23
|
-
|
|
27
|
+
# @param metadata [String, nil] partition metadata
|
|
28
|
+
def initialize(partition, offset, err = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR, metadata = nil)
|
|
24
29
|
@partition = partition
|
|
25
30
|
@offset = offset
|
|
26
31
|
@err = err
|
|
32
|
+
@metadata = metadata
|
|
27
33
|
end
|
|
28
34
|
|
|
29
35
|
# Human readable representation of this partition.
|
|
@@ -32,6 +38,7 @@ module Rdkafka
|
|
|
32
38
|
message = "<Partition #{partition}"
|
|
33
39
|
message += " offset=#{offset}" if offset
|
|
34
40
|
message += " err=#{err}" if err != Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
41
|
+
message += " metadata=#{metadata}" if !metadata.nil?
|
|
35
42
|
message += ">"
|
|
36
43
|
message
|
|
37
44
|
end
|