rdkafka 0.28.0 → 0.29.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +1 -0
- data/dist/{librdkafka-2.14.1.tar.gz → librdkafka-2.14.2.tar.gz} +0 -0
- data/docker-compose-ssl.yml +1 -1
- data/docker-compose.yml +1 -1
- 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_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_topic_handle.rb +4 -6
- data/lib/rdkafka/admin/describe_acl_handle.rb +5 -7
- 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_offsets_handle.rb +5 -10
- data/lib/rdkafka/admin.rb +75 -43
- data/lib/rdkafka/bindings.rb +9 -4
- 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_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_offsets_handler.rb +42 -0
- data/lib/rdkafka/callbacks.rb +50 -244
- data/lib/rdkafka/config.rb +45 -33
- data/lib/rdkafka/consumer/headers.rb +19 -5
- data/lib/rdkafka/consumer/partition.rb +8 -1
- data/lib/rdkafka/consumer/topic_partition_list.rb +44 -22
- data/lib/rdkafka/consumer.rb +111 -21
- data/lib/rdkafka/defaults.rb +19 -0
- data/lib/rdkafka/helpers/metadata.rb +29 -0
- data/lib/rdkafka/metadata.rb +86 -19
- data/lib/rdkafka/native_kafka.rb +2 -4
- data/lib/rdkafka/producer/delivery_handle.rb +3 -3
- data/lib/rdkafka/producer/partitions_count_cache.rb +24 -38
- data/lib/rdkafka/producer.rb +56 -44
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +12 -0
- data/package-lock.json +3 -3
- data/rdkafka.gemspec +1 -0
- metadata +14 -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_INCREMENTALALTERCONFIGS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class IncrementalAlterConfigsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the incremental-alter-configs handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
incremental_alter = IncrementalAlterConfigsResult.new(event_ptr)
|
|
14
|
+
incremental_alter_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
if incremental_alter_handle = Rdkafka::Admin::IncrementalAlterConfigsHandle.remove(incremental_alter_handle_ptr.address)
|
|
17
|
+
incremental_alter_handle[:response] = incremental_alter.result_error
|
|
18
|
+
incremental_alter_handle.broker_message = read_event_string(incremental_alter.error_string)
|
|
19
|
+
|
|
20
|
+
# Parsing can raise on per-resource errors. The exception is captured and re-raised on
|
|
21
|
+
# the waiting thread, since an exception leaving this callback would unwind through
|
|
22
|
+
# librdkafka native frames.
|
|
23
|
+
incremental_alter_handle.result = begin
|
|
24
|
+
if incremental_alter.result_error == Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
25
|
+
Rdkafka::Admin::IncrementalAlterConfigsReport.new(
|
|
26
|
+
config_entries: incremental_alter.results,
|
|
27
|
+
entry_count: incremental_alter.results_count
|
|
28
|
+
)
|
|
29
|
+
else
|
|
30
|
+
Rdkafka::Admin::IncrementalAlterConfigsReport.new(config_entries: FFI::Pointer::NULL, entry_count: 0)
|
|
31
|
+
end
|
|
32
|
+
rescue => e
|
|
33
|
+
e
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
incremental_alter_handle.unlock
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -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,26 @@ 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::RD_KAFKA_EVENT_CREATEACLS_RESULT
|
|
223
|
-
process_create_acl(event_ptr)
|
|
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
|
|
334
|
-
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
|
-
|
|
348
|
-
if create_partitions_handle = Rdkafka::Admin::CreatePartitionsHandle.remove(create_partitions_handle_ptr.address)
|
|
349
|
-
create_partitions_handle[:response] = create_partitions_results[0].result_error
|
|
350
|
-
create_partitions_handle[:error_string] = create_partitions_results[0].error_string
|
|
351
|
-
create_partitions_handle[:result_name] = create_partitions_results[0].result_name
|
|
352
|
-
|
|
353
|
-
create_partitions_handle.unlock
|
|
354
|
-
end
|
|
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
|
|
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_CREATEACLS_RESULT then CreateAclHandler
|
|
217
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT then DeleteAclHandler
|
|
218
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT then DescribeAclHandler
|
|
219
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBECONFIGS_RESULT then DescribeConfigsHandler
|
|
220
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT then IncrementalAlterConfigsHandler
|
|
221
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTOFFSETS_RESULT then ListOffsetsHandler
|
|
416
222
|
end
|
|
417
|
-
end
|
|
418
223
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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
|
|
224
|
+
handler&.call(event_ptr)
|
|
225
|
+
ensure
|
|
226
|
+
# Background queue events are owned by the application and must be destroyed once
|
|
227
|
+
# served (see rd_kafka_conf_set_background_event_cb). All event-owned memory (result
|
|
228
|
+
# arrays, strings) has to be copied into Ruby objects by the handlers above before this
|
|
229
|
+
# runs - nothing may retain pointers into the event past this point.
|
|
230
|
+
Rdkafka::Bindings.rd_kafka_event_destroy(event_ptr)
|
|
437
231
|
end
|
|
438
232
|
end
|
|
439
233
|
|
|
@@ -453,23 +247,35 @@ module Rdkafka
|
|
|
453
247
|
delivery_handle[:response] = message[:err]
|
|
454
248
|
delivery_handle[:partition] = message[:partition]
|
|
455
249
|
delivery_handle[:offset] = message[:offset]
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
#
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
250
|
+
# The topic is not stored on the handle here: it is already set as the handle's
|
|
251
|
+
# `topic` Ruby attribute during produce, which spares a native string copy that
|
|
252
|
+
# would otherwise be allocated and retained for every message.
|
|
253
|
+
|
|
254
|
+
begin
|
|
255
|
+
# Call delivery callback on opaque
|
|
256
|
+
if opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
|
|
257
|
+
opaque.call_delivery_callback(
|
|
258
|
+
Rdkafka::Producer::DeliveryReport.new(
|
|
259
|
+
message[:partition],
|
|
260
|
+
message[:offset],
|
|
261
|
+
topic_name,
|
|
262
|
+
message[:err],
|
|
263
|
+
delivery_handle.label
|
|
264
|
+
),
|
|
265
|
+
delivery_handle
|
|
266
|
+
)
|
|
267
|
+
end
|
|
268
|
+
rescue Exception => err
|
|
269
|
+
# A user delivery callback that raises must not escape this FFI callback: it runs on
|
|
270
|
+
# librdkafka's polling thread (abort_on_exception = true), so an escaping exception
|
|
271
|
+
# would crash the whole process. We log and swallow it, matching the rebalance
|
|
272
|
+
# callback. The `ensure` below still unlocks the handle, so `wait` returns the
|
|
273
|
+
# delivery report instead of blocking until its timeout and raising
|
|
274
|
+
# WaitTimeoutError for a message that was in fact delivered.
|
|
275
|
+
Rdkafka::Config.logger.error("Unhandled exception: #{err.class} - #{err.message}")
|
|
276
|
+
ensure
|
|
277
|
+
delivery_handle.unlock
|
|
470
278
|
end
|
|
471
|
-
|
|
472
|
-
delivery_handle.unlock
|
|
473
279
|
end
|
|
474
280
|
end
|
|
475
281
|
end
|
data/lib/rdkafka/config.rb
CHANGED
|
@@ -342,47 +342,55 @@ module Rdkafka
|
|
|
342
342
|
# @param opaque [Object, nil] optional opaque pointer for callbacks
|
|
343
343
|
# @return [FFI::Pointer] native rdkafka configuration pointer
|
|
344
344
|
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
|
-
|
|
345
|
+
config = Rdkafka::Bindings.rd_kafka_conf_new
|
|
346
|
+
|
|
347
|
+
# Create config
|
|
348
|
+
@config_hash.merge(REQUIRED_CONFIG).each do |key, value|
|
|
349
|
+
error_buffer = FFI::MemoryPointer.from_string(" " * 256)
|
|
350
|
+
result = Rdkafka::Bindings.rd_kafka_conf_set(
|
|
351
|
+
config,
|
|
352
|
+
key.to_s,
|
|
353
|
+
value.to_s,
|
|
354
|
+
error_buffer,
|
|
355
|
+
256
|
|
356
|
+
)
|
|
357
|
+
unless result == :config_ok
|
|
358
|
+
raise ConfigError.new(error_buffer.read_string)
|
|
359
359
|
end
|
|
360
|
+
end
|
|
360
361
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
362
|
+
# Set opaque pointer that's used as a proxy for callbacks
|
|
363
|
+
if opaque
|
|
364
|
+
pointer = ::FFI::Pointer.new(:pointer, opaque.object_id)
|
|
365
|
+
Rdkafka::Bindings.rd_kafka_conf_set_opaque(config, pointer)
|
|
365
366
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
367
|
+
# Store opaque with the pointer as key. We use this approach instead
|
|
368
|
+
# of trying to convert the pointer to a Ruby object because there is
|
|
369
|
+
# no risk of a segfault this way.
|
|
370
|
+
Rdkafka::Config.opaques[pointer.to_i] = opaque
|
|
371
|
+
end
|
|
371
372
|
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
# Set log callback
|
|
374
|
+
Rdkafka::Bindings.rd_kafka_conf_set_log_cb(config, Rdkafka::Bindings::LogCallback)
|
|
374
375
|
|
|
375
|
-
|
|
376
|
-
|
|
376
|
+
# Set stats callback
|
|
377
|
+
Rdkafka::Bindings.rd_kafka_conf_set_stats_cb(config, Rdkafka::Bindings::StatsCallback)
|
|
377
378
|
|
|
378
|
-
|
|
379
|
-
|
|
379
|
+
# Set error callback
|
|
380
|
+
Rdkafka::Bindings.rd_kafka_conf_set_error_cb(config, Rdkafka::Bindings::ErrorCallback)
|
|
380
381
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
end
|
|
382
|
+
# Set oauth callback
|
|
383
|
+
if Rdkafka::Config.oauthbearer_token_refresh_callback
|
|
384
|
+
Rdkafka::Bindings.rd_kafka_conf_set_oauthbearer_token_refresh_cb(config, Rdkafka::Bindings::OAuthbearerTokenRefreshCallback)
|
|
385
385
|
end
|
|
386
|
+
|
|
387
|
+
config
|
|
388
|
+
rescue Exception
|
|
389
|
+
# rd_kafka_conf_new allocates a conf the caller owns until it is handed to rd_kafka_new. If
|
|
390
|
+
# we raise before returning it (e.g. an invalid option in the loop above), destroy it here
|
|
391
|
+
# so the native config is not leaked.
|
|
392
|
+
Rdkafka::Bindings.rd_kafka_conf_destroy(config) if config
|
|
393
|
+
raise
|
|
386
394
|
end
|
|
387
395
|
|
|
388
396
|
# Creates a native Kafka handle
|
|
@@ -400,6 +408,10 @@ module Rdkafka
|
|
|
400
408
|
)
|
|
401
409
|
|
|
402
410
|
if handle.null?
|
|
411
|
+
# On success rd_kafka_new takes ownership of the conf and frees it itself; on failure
|
|
412
|
+
# librdkafka keeps application ownership (see rdkafka.c), so we must destroy it here to
|
|
413
|
+
# avoid leaking the conf on every failed client creation.
|
|
414
|
+
Rdkafka::Bindings.rd_kafka_conf_destroy(config)
|
|
403
415
|
raise ClientCreationError.new(error_buffer.read_string)
|
|
404
416
|
end
|
|
405
417
|
|
|
@@ -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
|