karafka-rdkafka 0.30.2-aarch64-linux-gnu → 0.32.0-aarch64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +100 -36
- data/README.md +3 -1
- data/docker-compose-ssl.yml +1 -0
- data/docker-compose.yml +1 -0
- data/ext/librdkafka.so +0 -0
- data/karafka-rdkafka.gemspec +5 -4
- data/lib/rdkafka/admin/acl_binding_result.rb +4 -16
- data/lib/rdkafka/admin/alter_consumer_group_offsets_report.rb +2 -2
- data/lib/rdkafka/admin/create_acl_report.rb +1 -3
- data/lib/rdkafka/admin/create_topic_report.rb +2 -6
- data/lib/rdkafka/admin/delete_consumer_group_offsets_report.rb +2 -2
- data/lib/rdkafka/admin/delete_groups_report.rb +2 -6
- data/lib/rdkafka/admin/delete_topic_report.rb +2 -6
- data/lib/rdkafka/admin/describe_cluster_handle.rb +31 -0
- data/lib/rdkafka/admin/describe_cluster_report.rb +51 -0
- data/lib/rdkafka/admin/describe_consumer_groups_handle.rb +31 -0
- data/lib/rdkafka/admin/describe_consumer_groups_report.rb +151 -0
- data/lib/rdkafka/admin/describe_result_parsing.rb +47 -0
- data/lib/rdkafka/admin/describe_topics_handle.rb +31 -0
- data/lib/rdkafka/admin/describe_topics_report.rb +118 -0
- data/lib/rdkafka/admin/list_consumer_group_offsets_handle.rb +31 -0
- data/lib/rdkafka/admin/list_consumer_group_offsets_report.rb +52 -0
- data/lib/rdkafka/admin.rb +424 -9
- data/lib/rdkafka/bindings/admin/acls.rb +85 -0
- data/lib/rdkafka/bindings/admin/configs.rb +37 -0
- data/lib/rdkafka/bindings/admin/list_offsets.rb +26 -0
- data/lib/rdkafka/bindings/admin.rb +211 -0
- data/lib/rdkafka/bindings/callbacks.rb +155 -0
- data/lib/rdkafka/bindings/configuration.rb +50 -0
- data/lib/rdkafka/bindings/consumer.rb +125 -0
- data/lib/rdkafka/bindings/errors.rb +17 -0
- data/lib/rdkafka/bindings/handle.rb +16 -0
- data/lib/rdkafka/bindings/messages.rb +28 -0
- data/lib/rdkafka/bindings/metadata.rb +17 -0
- data/lib/rdkafka/bindings/polling.rb +17 -0
- data/lib/rdkafka/bindings/producer.rb +82 -0
- data/lib/rdkafka/bindings/share_consumer.rb +67 -0
- data/lib/rdkafka/bindings/structs.rb +62 -0
- data/lib/rdkafka/bindings.rb +16 -775
- data/lib/rdkafka/callbacks/describe_cluster_handler.rb +36 -0
- data/lib/rdkafka/callbacks/describe_consumer_groups_handler.rb +36 -0
- data/lib/rdkafka/callbacks/describe_topics_handler.rb +36 -0
- data/lib/rdkafka/callbacks/list_consumer_group_offsets_handler.rb +62 -0
- data/lib/rdkafka/callbacks.rb +15 -7
- data/lib/rdkafka/clients.rb +13 -46
- data/lib/rdkafka/config.rb +70 -0
- data/lib/rdkafka/consumer/allocator.rb +0 -2
- data/lib/rdkafka/consumer/message.rb +6 -9
- data/lib/rdkafka/consumer/topic_partition_list.rb +7 -7
- data/lib/rdkafka/consumer.rb +76 -36
- data/lib/rdkafka/defaults.rb +6 -4
- data/lib/rdkafka/native_kafka.rb +45 -31
- data/lib/rdkafka/producer/delivery_handle.rb +18 -16
- data/lib/rdkafka/producer/delivery_report.rb +51 -1
- data/lib/rdkafka/producer/partitions_count_cache.rb +109 -26
- data/lib/rdkafka/producer.rb +141 -71
- data/lib/rdkafka/share_consumer.rb +70 -34
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +14 -1
- data/package-lock.json +9 -9
- data/renovate.json +7 -0
- metadata +31 -31
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_DESCRIBECLUSTER_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class DescribeClusterHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the describe cluster handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
result_ptr = Rdkafka::Bindings.rd_kafka_event_DescribeCluster_result(event_ptr)
|
|
14
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
return unless (handle = Rdkafka::Admin::DescribeClusterHandle.remove(handle_ptr.address))
|
|
17
|
+
|
|
18
|
+
return if resolve_operation_error(event_ptr, handle)
|
|
19
|
+
|
|
20
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
21
|
+
|
|
22
|
+
# Parsing must copy everything out of event-owned memory before the event is destroyed.
|
|
23
|
+
# An exception here is captured and re-raised on the waiting thread, since it cannot
|
|
24
|
+
# unwind through librdkafka native frames.
|
|
25
|
+
handle.result = begin
|
|
26
|
+
Rdkafka::Admin::DescribeClusterReport.new(result_ptr)
|
|
27
|
+
rescue => e
|
|
28
|
+
e
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
handle.unlock
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class DescribeConsumerGroupsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the describe-consumer-groups handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
result_ptr = Rdkafka::Bindings.rd_kafka_event_DescribeConsumerGroups_result(event_ptr)
|
|
14
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
return unless (handle = Rdkafka::Admin::DescribeConsumerGroupsHandle.remove(handle_ptr.address))
|
|
17
|
+
|
|
18
|
+
return if resolve_operation_error(event_ptr, handle)
|
|
19
|
+
|
|
20
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
21
|
+
|
|
22
|
+
# Parsing must copy everything out of event-owned memory before the event is destroyed.
|
|
23
|
+
# An exception here is captured and re-raised on the waiting thread, since it cannot
|
|
24
|
+
# unwind through librdkafka native frames.
|
|
25
|
+
handle.result = begin
|
|
26
|
+
Rdkafka::Admin::DescribeConsumerGroupsReport.new(result_ptr)
|
|
27
|
+
rescue => e
|
|
28
|
+
e
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
handle.unlock
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_DESCRIBETOPICS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class DescribeTopicsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the describe topics handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
result_ptr = Rdkafka::Bindings.rd_kafka_event_DescribeTopics_result(event_ptr)
|
|
14
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
return unless (handle = Rdkafka::Admin::DescribeTopicsHandle.remove(handle_ptr.address))
|
|
17
|
+
|
|
18
|
+
return if resolve_operation_error(event_ptr, handle)
|
|
19
|
+
|
|
20
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
21
|
+
|
|
22
|
+
# Parsing must copy everything out of event-owned memory before the event is destroyed.
|
|
23
|
+
# An exception here is captured and re-raised on the waiting thread, since it cannot
|
|
24
|
+
# unwind through librdkafka native frames.
|
|
25
|
+
handle.result = begin
|
|
26
|
+
Rdkafka::Admin::DescribeTopicsReport.new(result_ptr)
|
|
27
|
+
rescue => e
|
|
28
|
+
e
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
handle.unlock
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_LISTCONSUMERGROUPOFFSETS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class ListConsumerGroupOffsetsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the list consumer group 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
|
+
result = Rdkafka::Bindings.rd_kafka_event_ListConsumerGroupOffsets_result(event_ptr)
|
|
14
|
+
|
|
15
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
16
|
+
group_result_array = Rdkafka::Bindings.rd_kafka_ListConsumerGroupOffsets_result_groups(result, pointer_to_size_t)
|
|
17
|
+
group_results = GroupResult.create_group_results_from_array(pointer_to_size_t.read_int, group_result_array)
|
|
18
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
19
|
+
|
|
20
|
+
if (handle = Rdkafka::Admin::ListConsumerGroupOffsetsHandle.remove(handle_ptr.address))
|
|
21
|
+
unless resolve_operation_error(event_ptr, handle)
|
|
22
|
+
group_result = group_results[0]
|
|
23
|
+
|
|
24
|
+
# librdkafka only supports one group per invocation
|
|
25
|
+
if group_result.nil?
|
|
26
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
27
|
+
handle.result = Rdkafka::Admin::ListConsumerGroupOffsetsReport.new(
|
|
28
|
+
FFI::Pointer::NULL,
|
|
29
|
+
FFI::Pointer::NULL
|
|
30
|
+
)
|
|
31
|
+
else
|
|
32
|
+
report = Rdkafka::Admin::ListConsumerGroupOffsetsReport.new(
|
|
33
|
+
group_result.error_string,
|
|
34
|
+
group_result.result_name,
|
|
35
|
+
Rdkafka::Bindings.rd_kafka_group_result_partitions(group_result_array.read_pointer)
|
|
36
|
+
)
|
|
37
|
+
handle.result = report
|
|
38
|
+
|
|
39
|
+
# The group level error can be clean while a partition failed (e.g.
|
|
40
|
+
# `unstable_offset_commit` with `require_stable_offsets`), which must not look
|
|
41
|
+
# like a committed offset of nil.
|
|
42
|
+
failed = report.partitions.find { |partition| partition[:error] }
|
|
43
|
+
|
|
44
|
+
if !group_result.result_error.zero?
|
|
45
|
+
handle[:response] = group_result.result_error
|
|
46
|
+
handle.broker_message = report.error_string
|
|
47
|
+
elsif failed
|
|
48
|
+
handle[:response] = failed[:error].rdkafka_response
|
|
49
|
+
handle.broker_message = "Failed for partition #{failed[:partition]} of '#{failed[:topic]}'"
|
|
50
|
+
else
|
|
51
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
handle.unlock
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/rdkafka/callbacks.rb
CHANGED
|
@@ -216,6 +216,7 @@ module Rdkafka
|
|
|
216
216
|
when Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT then CreatePartitionsHandler
|
|
217
217
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT then DeleteGroupsHandler
|
|
218
218
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_ALTERCONSUMERGROUPOFFSETS_RESULT then AlterConsumerGroupOffsetsHandler
|
|
219
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTCONSUMERGROUPOFFSETS_RESULT then ListConsumerGroupOffsetsHandler
|
|
219
220
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETECONSUMERGROUPOFFSETS_RESULT then DeleteConsumerGroupOffsetsHandler
|
|
220
221
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETERECORDS_RESULT then DeleteRecordsHandler
|
|
221
222
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT then CreateAclHandler
|
|
@@ -225,6 +226,9 @@ module Rdkafka
|
|
|
225
226
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT then IncrementalAlterConfigsHandler
|
|
226
227
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTOFFSETS_RESULT then ListOffsetsHandler
|
|
227
228
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT then ListConsumerGroupsHandler
|
|
229
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT then DescribeConsumerGroupsHandler
|
|
230
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBECLUSTER_RESULT then DescribeClusterHandler
|
|
231
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBETOPICS_RESULT then DescribeTopicsHandler
|
|
228
232
|
end
|
|
229
233
|
|
|
230
234
|
handler&.call(event_ptr)
|
|
@@ -247,15 +251,16 @@ module Rdkafka
|
|
|
247
251
|
message = Rdkafka::Bindings::Message.new(message_ptr)
|
|
248
252
|
delivery_handle_ptr_address = message[:_private].address
|
|
249
253
|
if delivery_handle = Rdkafka::Producer::DeliveryHandle.remove(delivery_handle_ptr_address)
|
|
250
|
-
topic_name = Rdkafka::Bindings.rd_kafka_topic_name(message[:rkt])
|
|
251
|
-
|
|
252
254
|
# Update delivery handle
|
|
253
255
|
delivery_handle[:response] = message[:err]
|
|
254
256
|
delivery_handle[:partition] = message[:partition]
|
|
255
257
|
delivery_handle[:offset] = message[:offset]
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
delivery_handle[:status] = Rdkafka::Bindings.rd_kafka_message_status(message_ptr)
|
|
259
|
+
delivery_handle[:latency] = Rdkafka::Bindings.rd_kafka_message_latency(message_ptr)
|
|
260
|
+
delivery_handle[:broker_id] = Rdkafka::Bindings.rd_kafka_message_broker_id(message_ptr)
|
|
261
|
+
# The topic is taken from the handle's `topic` Ruby attribute set during produce, not
|
|
262
|
+
# read back from librdkafka, which spares an FFI call and a native string copy for
|
|
263
|
+
# every message.
|
|
259
264
|
|
|
260
265
|
begin
|
|
261
266
|
# Call delivery callback on opaque
|
|
@@ -264,9 +269,12 @@ module Rdkafka
|
|
|
264
269
|
Rdkafka::Producer::DeliveryReport.new(
|
|
265
270
|
message[:partition],
|
|
266
271
|
message[:offset],
|
|
267
|
-
|
|
272
|
+
delivery_handle.topic,
|
|
268
273
|
message[:err],
|
|
269
|
-
delivery_handle.label
|
|
274
|
+
delivery_handle.label,
|
|
275
|
+
status: delivery_handle[:status],
|
|
276
|
+
latency: delivery_handle[:latency],
|
|
277
|
+
broker_id: delivery_handle[:broker_id]
|
|
270
278
|
),
|
|
271
279
|
delivery_handle
|
|
272
280
|
)
|
data/lib/rdkafka/clients.rb
CHANGED
|
@@ -4,22 +4,10 @@ module Rdkafka
|
|
|
4
4
|
# Tracks live public clients so they can be closed before Ruby begins forced finalization.
|
|
5
5
|
# @private
|
|
6
6
|
module Clients
|
|
7
|
-
# Ruby rewrote `ObjectSpace::WeakMap` in 3.3. On 3.2 and earlier its `[]` can hand back a
|
|
8
|
-
# foreign or already-freed object for a key, which raises `NoMethodError` or segfaults the VM
|
|
9
|
-
# the moment the value is touched. Track weakly only where that is safe and fall back to a
|
|
10
|
-
# strong registry - pruned as clients close - on older Rubies. The strong registry holds an
|
|
11
|
-
# open, un-closed client until shutdown, which is exactly when this cleanup needs it anyway.
|
|
12
|
-
WEAK_TRACKING = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.3")
|
|
13
|
-
|
|
14
7
|
@pid = Process.pid
|
|
15
8
|
@mutex = Mutex.new
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@clients = ObjectSpace::WeakMap.new
|
|
19
|
-
@tokens = [].freeze
|
|
20
|
-
else
|
|
21
|
-
@clients = {}.freeze
|
|
22
|
-
end
|
|
9
|
+
@clients = ObjectSpace::WeakMap.new
|
|
10
|
+
@tokens = [].freeze
|
|
23
11
|
|
|
24
12
|
# Registers a successfully constructed client so it can be closed during process shutdown.
|
|
25
13
|
# @param client [Consumer, Producer, Admin] client to close during process shutdown
|
|
@@ -28,21 +16,14 @@ module Rdkafka
|
|
|
28
16
|
reset_after_fork
|
|
29
17
|
|
|
30
18
|
@mutex.synchronize do
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@tokens = (@tokens + [token]).freeze
|
|
40
|
-
else
|
|
41
|
-
# Strong references, so drop clients that have already been closed to bound growth.
|
|
42
|
-
live = @clients.reject { |_id, existing| existing.closed? }
|
|
43
|
-
live[client.object_id] = client
|
|
44
|
-
@clients = live.freeze
|
|
45
|
-
end
|
|
19
|
+
live_clients
|
|
20
|
+
|
|
21
|
+
# The strongly-held token is the key and the client is the weak value, so registering a
|
|
22
|
+
# client never keeps it alive. Enumerating weak keys can expose reclaimed slots, so we
|
|
23
|
+
# look the value up by token instead.
|
|
24
|
+
token = Object.new
|
|
25
|
+
@clients[token] = client
|
|
26
|
+
@tokens = (@tokens + [token]).freeze
|
|
46
27
|
end
|
|
47
28
|
|
|
48
29
|
client
|
|
@@ -54,7 +35,7 @@ module Rdkafka
|
|
|
54
35
|
def self.close_all
|
|
55
36
|
return unless @pid == Process.pid
|
|
56
37
|
|
|
57
|
-
clients = @mutex.synchronize {
|
|
38
|
+
clients = @mutex.synchronize { live_clients }
|
|
58
39
|
first_error = nil
|
|
59
40
|
|
|
60
41
|
clients.each do |client|
|
|
@@ -66,16 +47,7 @@ module Rdkafka
|
|
|
66
47
|
raise first_error if first_error
|
|
67
48
|
end
|
|
68
49
|
|
|
69
|
-
# Returns the currently registered live clients.
|
|
70
|
-
# @return [Array<Consumer, Producer, Admin>] live clients
|
|
71
|
-
# @private
|
|
72
|
-
def self.current_clients
|
|
73
|
-
WEAK_TRACKING ? live_clients : @clients.values
|
|
74
|
-
end
|
|
75
|
-
private_class_method :current_clients
|
|
76
|
-
|
|
77
50
|
# Returns the live clients and releases tokens whose clients have been collected.
|
|
78
|
-
# Weak-tracking Rubies only.
|
|
79
51
|
# @return [Array<Consumer, Producer, Admin>] live clients
|
|
80
52
|
# @private
|
|
81
53
|
def self.live_clients
|
|
@@ -99,13 +71,8 @@ module Rdkafka
|
|
|
99
71
|
def self.reset_after_fork
|
|
100
72
|
return if @pid == Process.pid
|
|
101
73
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@tokens = [].freeze
|
|
105
|
-
else
|
|
106
|
-
@clients = {}.freeze
|
|
107
|
-
end
|
|
108
|
-
|
|
74
|
+
@clients = ObjectSpace::WeakMap.new
|
|
75
|
+
@tokens = [].freeze
|
|
109
76
|
@pid = Process.pid
|
|
110
77
|
@mutex = Mutex.new
|
|
111
78
|
end
|
data/lib/rdkafka/config.rb
CHANGED
|
@@ -156,6 +156,25 @@ module Rdkafka
|
|
|
156
156
|
)
|
|
157
157
|
end
|
|
158
158
|
|
|
159
|
+
# Returns the time-to-live of the process-wide partitions count cache used by
|
|
160
|
+
# `produce(partition_key:)`.
|
|
161
|
+
#
|
|
162
|
+
# @return [Integer] time-to-live in milliseconds
|
|
163
|
+
def self.partition_count_cache_ttl_ms
|
|
164
|
+
Rdkafka::Producer.partitions_count_cache.ttl_ms
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Sets the time-to-live of the process-wide partitions count cache shared by all the producers.
|
|
168
|
+
# Cached counts are kept, so it can be changed at any time.
|
|
169
|
+
#
|
|
170
|
+
# @param value [Integer] time-to-live in milliseconds
|
|
171
|
+
# (defaults to {Defaults::PARTITIONS_COUNT_CACHE_TTL_MS})
|
|
172
|
+
# @return [void]
|
|
173
|
+
# @raise [ArgumentError] when the value is not a positive Integer
|
|
174
|
+
def self.partition_count_cache_ttl_ms=(value)
|
|
175
|
+
Rdkafka::Producer.partitions_count_cache.ttl_ms = value
|
|
176
|
+
end
|
|
177
|
+
|
|
159
178
|
# @private
|
|
160
179
|
def self.opaques
|
|
161
180
|
@@opaques
|
|
@@ -180,6 +199,7 @@ module Rdkafka
|
|
|
180
199
|
|
|
181
200
|
@config_hash = DEFAULT_CONFIG.merge(config_hash)
|
|
182
201
|
@consumer_rebalance_listener = nil
|
|
202
|
+
@consumer_offset_commit_listener = nil
|
|
183
203
|
@consumer_poll_set = true
|
|
184
204
|
end
|
|
185
205
|
|
|
@@ -207,6 +227,20 @@ module Rdkafka
|
|
|
207
227
|
# @return [Object, #on_partitions_assigned, #on_partitions_revoked] listener instance
|
|
208
228
|
attr_writer :consumer_rebalance_listener
|
|
209
229
|
|
|
230
|
+
# Get the result of every offset commit, including async commits that the broker rejects
|
|
231
|
+
#
|
|
232
|
+
# `#on_offsets_committed` gets an {RdkafkaError} (nil on success) and the
|
|
233
|
+
# {Consumer::TopicPartitionList} of the commit, whose partitions carry their own errors. It
|
|
234
|
+
# runs inside {Consumer#poll} (or {Consumer#events_poll} when `consumer_poll_set` is false)
|
|
235
|
+
# and inside {Consumer#close}, on the thread that calls them.
|
|
236
|
+
#
|
|
237
|
+
# `#on_offsets_commit_failed` gets the same arguments, but only for a failed commit: not on
|
|
238
|
+
# success and not on `no_offset` (nothing new to commit). A listener with only this method
|
|
239
|
+
# costs nothing for the other commits.
|
|
240
|
+
#
|
|
241
|
+
# @return [Object, #on_offsets_committed, #on_offsets_commit_failed] listener instance
|
|
242
|
+
attr_writer :consumer_offset_commit_listener
|
|
243
|
+
|
|
210
244
|
# Should we use a single queue for the underlying consumer and events.
|
|
211
245
|
#
|
|
212
246
|
# This is an advanced API that allows for more granular control of the polling process.
|
|
@@ -243,6 +277,11 @@ module Rdkafka
|
|
|
243
277
|
Rdkafka::Bindings.rd_kafka_conf_set_rebalance_cb(config, Rdkafka::Bindings::RebalanceCallback)
|
|
244
278
|
end
|
|
245
279
|
|
|
280
|
+
if @consumer_offset_commit_listener
|
|
281
|
+
opaque.consumer_offset_commit_listener = @consumer_offset_commit_listener
|
|
282
|
+
Rdkafka::Bindings.rd_kafka_conf_set_offset_commit_cb(config, Rdkafka::Bindings::OffsetCommitCallback)
|
|
283
|
+
end
|
|
284
|
+
|
|
246
285
|
build_native_client(
|
|
247
286
|
config,
|
|
248
287
|
:rd_kafka_consumer,
|
|
@@ -598,6 +637,7 @@ module Rdkafka
|
|
|
598
637
|
class Opaque
|
|
599
638
|
attr_accessor :producer
|
|
600
639
|
attr_accessor :consumer_rebalance_listener
|
|
640
|
+
attr_accessor :consumer_offset_commit_listener
|
|
601
641
|
# Backreference set for share consumers so conf-level callbacks (which receive the opaque)
|
|
602
642
|
# can hand instance-scoped data - currently the librdkafka client name - back to the
|
|
603
643
|
# ShareConsumer, which has no native accessor for it
|
|
@@ -635,5 +675,35 @@ module Rdkafka
|
|
|
635
675
|
|
|
636
676
|
consumer_rebalance_listener.on_partitions_revoked(list)
|
|
637
677
|
end
|
|
678
|
+
|
|
679
|
+
# Invokes the on_offsets_committed callback on the offset commit listener if set
|
|
680
|
+
# @param error [Rdkafka::RdkafkaError, nil] the commit error or nil on success
|
|
681
|
+
# @param list [Rdkafka::Consumer::TopicPartitionList] the offsets of the commit
|
|
682
|
+
def call_on_offsets_committed(error, list)
|
|
683
|
+
return unless consumer_offset_commit_listener
|
|
684
|
+
return unless consumer_offset_commit_listener.respond_to?(:on_offsets_committed)
|
|
685
|
+
|
|
686
|
+
consumer_offset_commit_listener.on_offsets_committed(error, list)
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
# Invokes the on_offsets_commit_failed callback on the offset commit listener if set
|
|
690
|
+
# @param error [Rdkafka::RdkafkaError] the commit error
|
|
691
|
+
# @param list [Rdkafka::Consumer::TopicPartitionList] the offsets of the commit
|
|
692
|
+
def call_on_offsets_commit_failed(error, list)
|
|
693
|
+
return unless consumer_offset_commit_listener
|
|
694
|
+
return unless consumer_offset_commit_listener.respond_to?(:on_offsets_commit_failed)
|
|
695
|
+
|
|
696
|
+
consumer_offset_commit_listener.on_offsets_commit_failed(error, list)
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
# @return [Boolean] true if the offset commit listener wants the result of every commit
|
|
700
|
+
def offsets_committed_listened?
|
|
701
|
+
consumer_offset_commit_listener.respond_to?(:on_offsets_committed)
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
# @return [Boolean] true if the offset commit listener wants the failed commits
|
|
705
|
+
def offsets_commit_failed_listened?
|
|
706
|
+
consumer_offset_commit_listener.respond_to?(:on_offsets_commit_failed)
|
|
707
|
+
end
|
|
638
708
|
end
|
|
639
709
|
end
|
|
@@ -35,19 +35,16 @@ module Rdkafka
|
|
|
35
35
|
# @param native_message [Rdkafka::Bindings::Message] native message struct from librdkafka
|
|
36
36
|
def initialize(native_message)
|
|
37
37
|
# Set topic
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
end
|
|
38
|
+
rkt = native_message[:rkt]
|
|
39
|
+
@topic = Rdkafka::Bindings.rd_kafka_topic_name(rkt) unless rkt.null?
|
|
41
40
|
# Set partition
|
|
42
41
|
@partition = native_message[:partition]
|
|
43
42
|
# Set payload
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
end
|
|
43
|
+
payload = native_message[:payload]
|
|
44
|
+
@payload = payload.read_string(native_message[:len]) unless payload.null?
|
|
47
45
|
# Set key
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end
|
|
46
|
+
key = native_message[:key]
|
|
47
|
+
@key = key.read_string(native_message[:key_len]) unless key.null?
|
|
51
48
|
# Set offset
|
|
52
49
|
@offset = native_message[:offset]
|
|
53
50
|
# Set timestamp
|
|
@@ -38,7 +38,7 @@ module Rdkafka
|
|
|
38
38
|
# Calling this method multiple times for the same topic will overwrite the previous
|
|
39
39
|
# configuraton.
|
|
40
40
|
#
|
|
41
|
-
# @param
|
|
41
|
+
# @param topic_name [String] The topic's name
|
|
42
42
|
# @param partitions [Array<Integer>, Range<Integer>, Integer] The topic's partitions or
|
|
43
43
|
# partition count
|
|
44
44
|
#
|
|
@@ -52,14 +52,14 @@ module Rdkafka
|
|
|
52
52
|
#
|
|
53
53
|
# @example Add a topic with all topics up to a count
|
|
54
54
|
# tpl.add_topic("topic", 9)
|
|
55
|
-
def add_topic(
|
|
55
|
+
def add_topic(topic_name, partitions = nil)
|
|
56
56
|
if partitions.nil?
|
|
57
|
-
@data[
|
|
57
|
+
@data[topic_name.to_s] = nil
|
|
58
58
|
else
|
|
59
59
|
if partitions.is_a? Integer
|
|
60
60
|
partitions = (0..partitions - 1)
|
|
61
61
|
end
|
|
62
|
-
@data[
|
|
62
|
+
@data[topic_name.to_s] = partitions.map { |p| Partition.new(p, nil, Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR) }
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -67,12 +67,12 @@ module Rdkafka
|
|
|
67
67
|
# Calling this method multiple times for the same topic will overwrite the previous
|
|
68
68
|
# configuraton.
|
|
69
69
|
#
|
|
70
|
-
# @param
|
|
70
|
+
# @param topic_name [String] The topic's name
|
|
71
71
|
# @param partitions_with_offsets [Hash{Integer => Integer}, Array<Consumer::Partition>] The
|
|
72
72
|
# topic's partitions and offsets (Hash) or partitions with offsets and metadata (Array)
|
|
73
73
|
# @return [nil]
|
|
74
|
-
def add_topic_and_partitions_with_offsets(
|
|
75
|
-
@data[
|
|
74
|
+
def add_topic_and_partitions_with_offsets(topic_name, partitions_with_offsets)
|
|
75
|
+
@data[topic_name.to_s] = partitions_with_offsets.map do |p, o|
|
|
76
76
|
p.is_a?(Partition) ? p : Partition.new(p, o)
|
|
77
77
|
end
|
|
78
78
|
end
|