karafka-rdkafka 0.28.0-aarch64-linux-gnu → 0.28.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 +37 -30
- data/README.md +3 -3
- data/ext/librdkafka.so +0 -0
- data/lib/rdkafka/admin/create_acl_report.rb +2 -1
- data/lib/rdkafka/admin/delete_records_handle.rb +31 -0
- data/lib/rdkafka/admin/delete_records_report.rb +25 -0
- data/lib/rdkafka/admin/describe_acl_report.rb +2 -1
- 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.rb +177 -8
- data/lib/rdkafka/bindings.rb +51 -13
- data/lib/rdkafka/callbacks/delete_records_handler.rb +38 -0
- data/lib/rdkafka/callbacks/list_consumer_groups_handler.rb +39 -0
- data/lib/rdkafka/callbacks.rb +4 -2
- data/lib/rdkafka/config.rb +19 -17
- data/lib/rdkafka/consumer/topic_partition_list.rb +14 -9
- data/lib/rdkafka/consumer.rb +37 -36
- data/lib/rdkafka/defaults.rb +11 -2
- data/lib/rdkafka/error.rb +2 -1
- data/lib/rdkafka/helpers/oauth.rb +10 -5
- data/lib/rdkafka/native_kafka.rb +20 -7
- data/lib/rdkafka/producer/delivery_handle.rb +1 -2
- data/lib/rdkafka/producer/testing.rb +2 -1
- data/lib/rdkafka/producer.rb +28 -20
- data/lib/rdkafka/version.rb +1 -1
- data/lib/rdkafka.rb +6 -0
- metadata +8 -2
data/lib/rdkafka/bindings.rb
CHANGED
|
@@ -88,7 +88,7 @@ module Rdkafka
|
|
|
88
88
|
|
|
89
89
|
# This function comes from our patch on top of librdkafka. It allows os to load all the
|
|
90
90
|
# librdkafka components without initializing the client
|
|
91
|
-
#
|
|
91
|
+
# See: https://github.com/confluentinc/librdkafka/issues/4590
|
|
92
92
|
attach_function :rd_kafka_global_init, [], :void
|
|
93
93
|
|
|
94
94
|
# Polling
|
|
@@ -271,10 +271,11 @@ module Rdkafka
|
|
|
271
271
|
|
|
272
272
|
# Queue IO Event Support - for fiber scheduler integration
|
|
273
273
|
# Enables notifications to a custom FD when queue transitions from empty to non-empty
|
|
274
|
-
#
|
|
275
|
-
#
|
|
276
|
-
#
|
|
277
|
-
#
|
|
274
|
+
# Arguments:
|
|
275
|
+
# - queue (rd_kafka_queue_t*) - the queue to monitor
|
|
276
|
+
# - fd (int) - file descriptor to write to (provide your own pipe/eventfd)
|
|
277
|
+
# - payload (const void*) - data to write to fd
|
|
278
|
+
# - size (size_t) - size of payload
|
|
278
279
|
attach_function :rd_kafka_queue_io_event_enable, [:pointer, :int, :pointer, :size_t], :void
|
|
279
280
|
# Per topic configs
|
|
280
281
|
attach_function :rd_kafka_topic_conf_new, [], :pointer
|
|
@@ -343,7 +344,8 @@ module Rdkafka
|
|
|
343
344
|
# across different parts of the codebase (callbacks, testing utilities, etc.).
|
|
344
345
|
#
|
|
345
346
|
# @param client_ptr [FFI::Pointer] Native kafka client pointer
|
|
346
|
-
# @return [Hash, nil] Hash with :error_code and :error_string if fatal error occurred,
|
|
347
|
+
# @return [Hash, nil] Hash with :error_code and :error_string if fatal error occurred,
|
|
348
|
+
# nil otherwise
|
|
347
349
|
#
|
|
348
350
|
# @example
|
|
349
351
|
# details = Rdkafka::Bindings.extract_fatal_error(client_ptr)
|
|
@@ -388,9 +390,10 @@ module Rdkafka
|
|
|
388
390
|
end
|
|
389
391
|
end
|
|
390
392
|
|
|
391
|
-
# The OAuth callback is currently global and contextless.
|
|
392
|
-
#
|
|
393
|
-
# The instance name will be provided in the callback, allowing the callback to
|
|
393
|
+
# The OAuth callback is currently global and contextless. This means that the callback will be
|
|
394
|
+
# called for all instances, and the callback must be able to determine to which instance it is
|
|
395
|
+
# associated. The instance name will be provided in the callback, allowing the callback to
|
|
396
|
+
# reference the correct instance.
|
|
394
397
|
#
|
|
395
398
|
# An example of how to use the instance name in the callback is given below.
|
|
396
399
|
# The `refresh_token` is configured as the `oauthbearer_token_refresh_callback`.
|
|
@@ -599,6 +602,37 @@ module Rdkafka
|
|
|
599
602
|
attach_function :rd_kafka_event_DeleteGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteGroups_result_t*
|
|
600
603
|
attach_function :rd_kafka_DeleteGroups_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteGroups_result_t*, size_t* => rd_kafka_group_result_t**
|
|
601
604
|
|
|
605
|
+
# Delete Records
|
|
606
|
+
RD_KAFKA_ADMIN_OP_DELETERECORDS = 6 # rd_kafka_admin_op_t
|
|
607
|
+
RD_KAFKA_EVENT_DELETERECORDS_RESULT = 105 # rd_kafka_event_type_t
|
|
608
|
+
|
|
609
|
+
attach_function :rd_kafka_DeleteRecords, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
|
|
610
|
+
attach_function :rd_kafka_DeleteRecords_new, [:pointer], :pointer, blocking: true
|
|
611
|
+
attach_function :rd_kafka_DeleteRecords_destroy, [:pointer], :void, blocking: true
|
|
612
|
+
attach_function :rd_kafka_event_DeleteRecords_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteRecords_result_t*
|
|
613
|
+
attach_function :rd_kafka_DeleteRecords_result_offsets, [:pointer], :pointer, blocking: true # rd_kafka_DeleteRecords_result_t* => rd_kafka_topic_partition_list_t*
|
|
614
|
+
|
|
615
|
+
# List Consumer Groups
|
|
616
|
+
RD_KAFKA_ADMIN_OP_LISTCONSUMERGROUPS = 12 # rd_kafka_admin_op_t
|
|
617
|
+
RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT = 0x2000 # rd_kafka_event_type_t
|
|
618
|
+
|
|
619
|
+
# Consumer group states (rd_kafka_consumer_group_state_t)
|
|
620
|
+
RD_KAFKA_CONSUMER_GROUP_STATE_UNKNOWN = 0
|
|
621
|
+
RD_KAFKA_CONSUMER_GROUP_STATE_PREPARING_REBALANCE = 1
|
|
622
|
+
RD_KAFKA_CONSUMER_GROUP_STATE_COMPLETING_REBALANCE = 2
|
|
623
|
+
RD_KAFKA_CONSUMER_GROUP_STATE_STABLE = 3
|
|
624
|
+
RD_KAFKA_CONSUMER_GROUP_STATE_DEAD = 4
|
|
625
|
+
RD_KAFKA_CONSUMER_GROUP_STATE_EMPTY = 5
|
|
626
|
+
|
|
627
|
+
attach_function :rd_kafka_ListConsumerGroups, [:pointer, :pointer, :pointer], :void, blocking: true
|
|
628
|
+
attach_function :rd_kafka_event_ListConsumerGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_ListConsumerGroups_result_t*
|
|
629
|
+
attach_function :rd_kafka_ListConsumerGroups_result_valid, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_ConsumerGroupListing_t**
|
|
630
|
+
attach_function :rd_kafka_ListConsumerGroups_result_errors, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_error_t**
|
|
631
|
+
attach_function :rd_kafka_ConsumerGroupListing_group_id, [:pointer], :pointer, blocking: true # => const char*
|
|
632
|
+
attach_function :rd_kafka_ConsumerGroupListing_is_simple_consumer_group, [:pointer], :int, blocking: true
|
|
633
|
+
attach_function :rd_kafka_ConsumerGroupListing_state, [:pointer], :int, blocking: true
|
|
634
|
+
attach_function :rd_kafka_consumer_group_state_name, [:int], :pointer, blocking: true # => const char*
|
|
635
|
+
|
|
602
636
|
# Background Queue and Callback
|
|
603
637
|
|
|
604
638
|
attach_function :rd_kafka_conf_set_background_event_cb, [:pointer, :pointer], :void
|
|
@@ -661,21 +695,24 @@ module Rdkafka
|
|
|
661
695
|
attach_function :rd_kafka_AclBindingFilter_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t], :pointer
|
|
662
696
|
attach_function :rd_kafka_AclBinding_destroy, [:pointer], :void
|
|
663
697
|
|
|
664
|
-
# rd_kafka_ResourceType_t -
|
|
698
|
+
# rd_kafka_ResourceType_t -
|
|
699
|
+
# https://github.com/confluentinc/librdkafka/blob/292d2a66b992/src/rdkafka.h#L7307
|
|
665
700
|
RD_KAFKA_RESOURCE_ANY = 1
|
|
666
701
|
RD_KAFKA_RESOURCE_TOPIC = 2
|
|
667
702
|
RD_KAFKA_RESOURCE_GROUP = 3
|
|
668
703
|
RD_KAFKA_RESOURCE_BROKER = 4
|
|
669
704
|
RD_KAFKA_RESOURCE_TRANSACTIONAL_ID = 5
|
|
670
705
|
|
|
671
|
-
# rd_kafka_ResourcePatternType_t -
|
|
706
|
+
# rd_kafka_ResourcePatternType_t -
|
|
707
|
+
# https://github.com/confluentinc/librdkafka/blob/292d2a66b992/src/rdkafka.h#L7320
|
|
672
708
|
RD_KAFKA_RESOURCE_PATTERN_UNKNOWN = 0
|
|
673
709
|
RD_KAFKA_RESOURCE_PATTERN_ANY = 1
|
|
674
710
|
RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
|
|
675
711
|
RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
|
|
676
712
|
RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
|
|
677
713
|
|
|
678
|
-
# rd_kafka_AclOperation_t -
|
|
714
|
+
# rd_kafka_AclOperation_t -
|
|
715
|
+
# https://github.com/confluentinc/librdkafka/blob/292d2a66b992/src/rdkafka.h#L8403
|
|
679
716
|
RD_KAFKA_ACL_OPERATION_ANY = 1
|
|
680
717
|
RD_KAFKA_ACL_OPERATION_ALL = 2
|
|
681
718
|
RD_KAFKA_ACL_OPERATION_READ = 3
|
|
@@ -689,7 +726,8 @@ module Rdkafka
|
|
|
689
726
|
RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
|
|
690
727
|
RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
|
|
691
728
|
|
|
692
|
-
# rd_kafka_AclPermissionType_t -
|
|
729
|
+
# rd_kafka_AclPermissionType_t -
|
|
730
|
+
# https://github.com/confluentinc/librdkafka/blob/292d2a66b992/src/rdkafka.h#L8435
|
|
693
731
|
RD_KAFKA_ACL_PERMISSION_TYPE_ANY = 1
|
|
694
732
|
RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
|
|
695
733
|
RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_DELETERECORDS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class DeleteRecordsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the delete-records 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_DeleteRecords_result(event_ptr)
|
|
14
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
return unless (handle = Rdkafka::Admin::DeleteRecordsHandle.remove(handle_ptr.address))
|
|
17
|
+
|
|
18
|
+
# An operation-level error (e.g. timeout or a closed client) is delivered on the event
|
|
19
|
+
# itself, with no per-partition result to parse.
|
|
20
|
+
return if resolve_operation_error(event_ptr, handle)
|
|
21
|
+
|
|
22
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
23
|
+
|
|
24
|
+
# Parsing must copy everything out of event-owned memory before the event is destroyed.
|
|
25
|
+
# An exception here is captured and re-raised on the waiting thread, since it cannot
|
|
26
|
+
# unwind through librdkafka native frames.
|
|
27
|
+
handle.result = begin
|
|
28
|
+
Rdkafka::Admin::DeleteRecordsReport.new(result_ptr)
|
|
29
|
+
rescue => e
|
|
30
|
+
e
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
handle.unlock
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class ListConsumerGroupsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the list-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_ListConsumerGroups_result(event_ptr)
|
|
14
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
15
|
+
|
|
16
|
+
return unless (handle = Rdkafka::Admin::ListConsumerGroupsHandle.remove(handle_ptr.address))
|
|
17
|
+
|
|
18
|
+
# An operation-level error (e.g. timeout or a closed client) is delivered on the event
|
|
19
|
+
# itself; per the source feature's all-or-nothing contract we surface it as the result
|
|
20
|
+
# rather than returning a partial listing.
|
|
21
|
+
return if resolve_operation_error(event_ptr, handle)
|
|
22
|
+
|
|
23
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
24
|
+
|
|
25
|
+
# Parsing must copy everything out of event-owned memory before the event is destroyed.
|
|
26
|
+
# An exception here is captured and re-raised on the waiting thread, since it cannot
|
|
27
|
+
# unwind through librdkafka native frames.
|
|
28
|
+
handle.result = begin
|
|
29
|
+
Rdkafka::Admin::ListConsumerGroupsReport.new(result_ptr)
|
|
30
|
+
rescue => e
|
|
31
|
+
e
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
handle.unlock
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/rdkafka/callbacks.rb
CHANGED
|
@@ -219,12 +219,14 @@ module Rdkafka
|
|
|
219
219
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT then DeleteTopicHandler
|
|
220
220
|
when Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT then CreatePartitionsHandler
|
|
221
221
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT then DeleteGroupsHandler
|
|
222
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETERECORDS_RESULT then DeleteRecordsHandler
|
|
222
223
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT then CreateAclHandler
|
|
223
224
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT then DeleteAclHandler
|
|
224
225
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT then DescribeAclHandler
|
|
225
226
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBECONFIGS_RESULT then DescribeConfigsHandler
|
|
226
227
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT then IncrementalAlterConfigsHandler
|
|
227
228
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTOFFSETS_RESULT then ListOffsetsHandler
|
|
229
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT then ListConsumerGroupsHandler
|
|
228
230
|
end
|
|
229
231
|
|
|
230
232
|
handler&.call(event_ptr)
|
|
@@ -286,9 +288,9 @@ module Rdkafka
|
|
|
286
288
|
end
|
|
287
289
|
end
|
|
288
290
|
|
|
289
|
-
#
|
|
291
|
+
# @!visibility private
|
|
290
292
|
@@mutex = Mutex.new
|
|
291
|
-
#
|
|
293
|
+
# @!visibility private
|
|
292
294
|
@@current_pid = nil
|
|
293
295
|
|
|
294
296
|
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
|
|
@@ -295,6 +297,9 @@ module Rdkafka
|
|
|
295
297
|
# Uses `rd_kafka_conf_dump` to retrieve every property (including defaults and
|
|
296
298
|
# internal properties like `client.software.name`) as a flat Hash.
|
|
297
299
|
#
|
|
300
|
+
# @return [Hash{Symbol => String}] property names mapped to their current values
|
|
301
|
+
#
|
|
302
|
+
# @raise [ConfigError] When the configuration contains invalid options
|
|
298
303
|
# @note The librdkafka C API does not distinguish between producer-only, consumer-only,
|
|
299
304
|
# and global properties at the configuration level. All properties are returned
|
|
300
305
|
# regardless of the intended client type.
|
|
@@ -302,10 +307,6 @@ module Rdkafka
|
|
|
302
307
|
# @note The returned Hash may include sensitive values such as authentication
|
|
303
308
|
# credentials and key passwords. Do not log or serialize the returned data
|
|
304
309
|
# unless you have explicitly redacted secret entries.
|
|
305
|
-
#
|
|
306
|
-
# @return [Hash{Symbol => String}] property names mapped to their current values
|
|
307
|
-
#
|
|
308
|
-
# @raise [ConfigError] When the configuration contains invalid options
|
|
309
310
|
def describe_properties
|
|
310
311
|
config = nil
|
|
311
312
|
dump_ptr = nil
|
|
@@ -330,7 +331,8 @@ module Rdkafka
|
|
|
330
331
|
Rdkafka::Bindings.rd_kafka_conf_destroy(config) if config
|
|
331
332
|
end
|
|
332
333
|
|
|
333
|
-
# 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.
|
|
334
336
|
class ConfigError < RuntimeError; end
|
|
335
337
|
|
|
336
338
|
# Error that is returned by the underlying rdkafka library if the client cannot be created.
|
|
@@ -6,7 +6,8 @@ module Rdkafka
|
|
|
6
6
|
class TopicPartitionList
|
|
7
7
|
# Create a topic partition list.
|
|
8
8
|
#
|
|
9
|
-
# @param data [Hash{String => nil,Partition}] The topic and partition data or nil to create an
|
|
9
|
+
# @param data [Hash{String => nil,Partition}] The topic and partition data or nil to create an
|
|
10
|
+
# empty list
|
|
10
11
|
#
|
|
11
12
|
# @return [TopicPartitionList]
|
|
12
13
|
def initialize(data = nil)
|
|
@@ -34,10 +35,12 @@ module Rdkafka
|
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
# Add a topic with optionally partitions to the list.
|
|
37
|
-
# Calling this method multiple times for the same topic will overwrite the previous
|
|
38
|
+
# Calling this method multiple times for the same topic will overwrite the previous
|
|
39
|
+
# configuraton.
|
|
38
40
|
#
|
|
39
41
|
# @param topic [String] The topic's name
|
|
40
|
-
# @param partitions [Array<Integer>, Range<Integer>, Integer] The topic's partitions or
|
|
42
|
+
# @param partitions [Array<Integer>, Range<Integer>, Integer] The topic's partitions or
|
|
43
|
+
# partition count
|
|
41
44
|
#
|
|
42
45
|
# @return [nil]
|
|
43
46
|
#
|
|
@@ -61,11 +64,12 @@ module Rdkafka
|
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
# Add a topic with partitions and offsets set to the list
|
|
64
|
-
# Calling this method multiple times for the same topic will overwrite the previous
|
|
67
|
+
# Calling this method multiple times for the same topic will overwrite the previous
|
|
68
|
+
# configuraton.
|
|
65
69
|
#
|
|
66
70
|
# @param topic [String] The topic's name
|
|
67
|
-
# @param partitions_with_offsets [Hash{Integer => Integer}, Array<Consumer::Partition>] The
|
|
68
|
-
# partitions and offsets (Hash) or partitions with offsets and metadata (Array)
|
|
71
|
+
# @param partitions_with_offsets [Hash{Integer => Integer}, Array<Consumer::Partition>] The
|
|
72
|
+
# topic's partitions and offsets (Hash) or partitions with offsets and metadata (Array)
|
|
69
73
|
# @return [nil]
|
|
70
74
|
def add_topic_and_partitions_with_offsets(topic, partitions_with_offsets)
|
|
71
75
|
@data[topic.to_s] = partitions_with_offsets.map do |p, o|
|
|
@@ -73,7 +77,8 @@ module Rdkafka
|
|
|
73
77
|
end
|
|
74
78
|
end
|
|
75
79
|
|
|
76
|
-
# Return a `Hash` with the topics as keys and and an array of partition information as the
|
|
80
|
+
# Return a `Hash` with the topics as keys and and an array of partition information as the
|
|
81
|
+
# value if present.
|
|
77
82
|
#
|
|
78
83
|
# @return [Hash{String => Array<Partition>,nil}]
|
|
79
84
|
def to_h
|
|
@@ -97,7 +102,8 @@ module Rdkafka
|
|
|
97
102
|
#
|
|
98
103
|
# @private
|
|
99
104
|
#
|
|
100
|
-
# @param pointer [FFI::Pointer] Optional pointer to an existing native list. Its contents will
|
|
105
|
+
# @param pointer [FFI::Pointer] Optional pointer to an existing native list. Its contents will
|
|
106
|
+
# be copied.
|
|
101
107
|
#
|
|
102
108
|
# @return [TopicPartitionList]
|
|
103
109
|
def self.from_native_tpl(pointer)
|
|
@@ -118,7 +124,6 @@ module Rdkafka
|
|
|
118
124
|
else
|
|
119
125
|
elem[:offset]
|
|
120
126
|
end
|
|
121
|
-
|
|
122
127
|
partition = Partition.new(
|
|
123
128
|
elem[:partition],
|
|
124
129
|
offset,
|
data/lib/rdkafka/consumer.rb
CHANGED
|
@@ -35,11 +35,13 @@ module Rdkafka
|
|
|
35
35
|
# consumer-queue reference, then destroy the native client. The default `NativeKafka#finalizer`
|
|
36
36
|
# went straight to `rd_kafka_destroy`, leaving the consumer-queue reference (from
|
|
37
37
|
# `rd_kafka_queue_get_consumer`, taken by `poll_batch`) dangling - which can make
|
|
38
|
-
# `rd_kafka_destroy` block inside the finalizer (process hang at GC/shutdown) or leak the
|
|
38
|
+
# `rd_kafka_destroy` block inside the finalizer (process hang at GC/shutdown) or leak the
|
|
39
|
+
# handle.
|
|
39
40
|
#
|
|
40
41
|
# @private
|
|
41
42
|
# @param native_kafka [NativeKafka] the wrapped native client
|
|
42
|
-
# @param queue_holder [Array] single-element holder carrying the consumer queue pointer
|
|
43
|
+
# @param queue_holder [Array] single-element holder carrying the consumer queue pointer
|
|
44
|
+
# (or empty)
|
|
43
45
|
# @return [Proc] finalizer proc that must not reference the consumer instance
|
|
44
46
|
def self.finalizer(native_kafka, queue_holder)
|
|
45
47
|
proc do
|
|
@@ -125,11 +127,6 @@ module Rdkafka
|
|
|
125
127
|
# @return [nil]
|
|
126
128
|
# @raise [Rdkafka::ClosedConsumerError] if called on a closed consumer
|
|
127
129
|
#
|
|
128
|
-
# @note This method holds the inner lock until the queue is empty or `:stop` is returned.
|
|
129
|
-
# Other consumer operations will wait until this method returns.
|
|
130
|
-
# @note This method is thread-safe as it uses @native_kafka.with_inner synchronization
|
|
131
|
-
# @note Do NOT use this if `consumer_poll_set` was set to `true`
|
|
132
|
-
#
|
|
133
130
|
# @example Drain all pending events
|
|
134
131
|
# consumer.events_poll_nb_each { |_count| }
|
|
135
132
|
#
|
|
@@ -138,6 +135,10 @@ module Rdkafka
|
|
|
138
135
|
# consumer.events_poll_nb_each do |_count|
|
|
139
136
|
# :stop if monotonic_now >= deadline
|
|
140
137
|
# end
|
|
138
|
+
# @note This method holds the inner lock until the queue is empty or `:stop` is returned.
|
|
139
|
+
# Other consumer operations will wait until this method returns.
|
|
140
|
+
# @note This method is thread-safe as it uses @native_kafka.with_inner synchronization
|
|
141
|
+
# @note Do NOT use this if `consumer_poll_set` was set to `true`
|
|
141
142
|
def events_poll_nb_each
|
|
142
143
|
closed_consumer_check(__method__)
|
|
143
144
|
|
|
@@ -163,14 +164,6 @@ module Rdkafka
|
|
|
163
164
|
# @raise [Rdkafka::ClosedConsumerError] if called on a closed consumer
|
|
164
165
|
# @raise [Rdkafka::RdkafkaError] if a Kafka error occurs while polling
|
|
165
166
|
#
|
|
166
|
-
# @note This method uses `rd_kafka_consumer_poll` to fetch messages, unlike
|
|
167
|
-
# `events_poll_nb_each` which uses `rd_kafka_poll` for event callbacks (delivery reports,
|
|
168
|
-
# statistics, etc.). For consumers, use this method to receive messages and
|
|
169
|
-
# `events_poll_nb_each` for processing background events.
|
|
170
|
-
# @note This method holds the inner lock for the duration. Other consumer operations
|
|
171
|
-
# will wait until this method returns.
|
|
172
|
-
# @note Timeout/max_messages logic should be implemented by the caller
|
|
173
|
-
#
|
|
174
167
|
# @example Process messages until queue is empty
|
|
175
168
|
# consumer.poll_nb_each do |message|
|
|
176
169
|
# process(message)
|
|
@@ -183,6 +176,13 @@ module Rdkafka
|
|
|
183
176
|
# count += 1
|
|
184
177
|
# :stop if count >= 10
|
|
185
178
|
# end
|
|
179
|
+
# @note This method uses `rd_kafka_consumer_poll` to fetch messages, unlike
|
|
180
|
+
# `events_poll_nb_each` which uses `rd_kafka_poll` for event callbacks (delivery reports,
|
|
181
|
+
# statistics, etc.). For consumers, use this method to receive messages and
|
|
182
|
+
# `events_poll_nb_each` for processing background events.
|
|
183
|
+
# @note This method holds the inner lock for the duration. Other consumer operations
|
|
184
|
+
# will wait until this method returns.
|
|
185
|
+
# @note Timeout/max_messages logic should be implemented by the caller
|
|
186
186
|
def poll_nb_each
|
|
187
187
|
closed_consumer_check(__method__)
|
|
188
188
|
|
|
@@ -437,9 +437,11 @@ module Rdkafka
|
|
|
437
437
|
end
|
|
438
438
|
|
|
439
439
|
# Return the current positions (offsets) for topics and partitions.
|
|
440
|
-
# The offset field of each requested partition will be set to the offset of the last consumed
|
|
440
|
+
# The offset field of each requested partition will be set to the offset of the last consumed
|
|
441
|
+
# message + 1, or nil in case there was no previous message.
|
|
441
442
|
#
|
|
442
|
-
# @param list [TopicPartitionList, nil] The topic with partitions to get the offsets for or nil
|
|
443
|
+
# @param list [TopicPartitionList, nil] The topic with partitions to get the offsets for or nil
|
|
444
|
+
# to use the current subscription.
|
|
443
445
|
#
|
|
444
446
|
# @return [TopicPartitionList]
|
|
445
447
|
#
|
|
@@ -592,7 +594,7 @@ module Rdkafka
|
|
|
592
594
|
# When using this `enable.auto.offset.store` should be set to `false` in the config.
|
|
593
595
|
#
|
|
594
596
|
# @param message [Rdkafka::Consumer::Message] The message which offset will be stored
|
|
595
|
-
# @param metadata [String, nil] commit metadata string
|
|
597
|
+
# @param metadata [String, nil] commit metadata string to store alongside the offset
|
|
596
598
|
# @return [nil]
|
|
597
599
|
# @raise [RdkafkaError] When storing the offset fails
|
|
598
600
|
def store_offset(message, metadata = nil)
|
|
@@ -646,9 +648,8 @@ module Rdkafka
|
|
|
646
648
|
seek_by(message.topic, message.partition, message.offset)
|
|
647
649
|
end
|
|
648
650
|
|
|
649
|
-
# Seek to a particular message by providing the topic, partition and offset.
|
|
650
|
-
#
|
|
651
|
-
# message at the given offset.
|
|
651
|
+
# Seek to a particular message by providing the topic, partition and offset. The next poll on
|
|
652
|
+
# the topic/partition will return the message at the given offset.
|
|
652
653
|
#
|
|
653
654
|
# @param topic [String] The topic in which to seek
|
|
654
655
|
# @param partition [Integer] The partition number to seek
|
|
@@ -875,7 +876,7 @@ module Rdkafka
|
|
|
875
876
|
# returns without further waiting.
|
|
876
877
|
#
|
|
877
878
|
# Error events (e.g. `:partition_eof`) are returned inline as {RdkafkaError} objects
|
|
878
|
-
# rather than raised, so callers receive the complete batch
|
|
879
|
+
# rather than raised, so callers receive the complete batch - both messages and errors -
|
|
879
880
|
# and can decide how to handle each. This is particularly useful when multiple partitions
|
|
880
881
|
# signal EOF simultaneously: all signals appear in the returned array rather than only
|
|
881
882
|
# the first one being raised and the rest silently discarded.
|
|
@@ -950,15 +951,15 @@ module Rdkafka
|
|
|
950
951
|
# particularly useful in fiber scheduler contexts where GVL release/reacquire
|
|
951
952
|
# overhead is wasteful since we don't expect to wait.
|
|
952
953
|
#
|
|
954
|
+
# @param timeout_ms [Integer] Timeout waiting for the first message
|
|
955
|
+
# (default: 0 for non-blocking)
|
|
956
|
+
# @param max_items [Integer] Maximum number of messages to return per call
|
|
957
|
+
# @return [Array<Message, RdkafkaError>] Batch of messages and/or error events in arrival order
|
|
958
|
+
# @raise [ClosedConsumerError] When called on a closed consumer
|
|
953
959
|
# @note Since the GVL is not released, a non-zero timeout_ms will block all Ruby
|
|
954
960
|
# threads/fibers for the duration. Use {#poll_batch} if you need a blocking wait.
|
|
955
961
|
#
|
|
956
962
|
# Error events are returned inline as {RdkafkaError} objects; see {#poll_batch} for details.
|
|
957
|
-
#
|
|
958
|
-
# @param timeout_ms [Integer] Timeout waiting for the first message (default: 0 for non-blocking)
|
|
959
|
-
# @param max_items [Integer] Maximum number of messages to return per call
|
|
960
|
-
# @return [Array<Message, RdkafkaError>] Batch of messages and/or error events in arrival order
|
|
961
|
-
# @raise [ClosedConsumerError] When called on a closed consumer
|
|
962
963
|
def poll_batch_nb(timeout_ms = 0, max_items: 100)
|
|
963
964
|
closed_consumer_check(__method__)
|
|
964
965
|
|
|
@@ -1085,7 +1086,15 @@ module Rdkafka
|
|
|
1085
1086
|
|
|
1086
1087
|
private
|
|
1087
1088
|
|
|
1088
|
-
#
|
|
1089
|
+
# Checks if the consumer is closed and raises an error if so
|
|
1090
|
+
# @param method [Symbol] name of the calling method for error context
|
|
1091
|
+
# @raise [ClosedConsumerError] when the consumer is closed
|
|
1092
|
+
def closed_consumer_check(method)
|
|
1093
|
+
raise Rdkafka::ClosedConsumerError.new(method) if closed?
|
|
1094
|
+
end
|
|
1095
|
+
alias_method :closed_check, :closed_consumer_check
|
|
1096
|
+
|
|
1097
|
+
# Reads a librdkafka-allocated string and frees the underlying native buffer.
|
|
1089
1098
|
#
|
|
1090
1099
|
# `rd_kafka_memberid`/`rd_kafka_clusterid` return a string the caller owns and must release
|
|
1091
1100
|
# with `rd_kafka_mem_free`; without this the buffer leaks on every call.
|
|
@@ -1101,14 +1110,6 @@ module Rdkafka
|
|
|
1101
1110
|
Rdkafka::Bindings.rd_kafka_mem_free(inner, ptr) unless ptr.null?
|
|
1102
1111
|
end
|
|
1103
1112
|
|
|
1104
|
-
# Checks if the consumer is closed and raises an error if so
|
|
1105
|
-
# @param method [Symbol] name of the calling method for error context
|
|
1106
|
-
# @raise [ClosedConsumerError] when the consumer is closed
|
|
1107
|
-
def closed_consumer_check(method)
|
|
1108
|
-
raise Rdkafka::ClosedConsumerError.new(method) if closed?
|
|
1109
|
-
end
|
|
1110
|
-
alias_method :closed_check, :closed_consumer_check
|
|
1111
|
-
|
|
1112
1113
|
# Reads this consumer's effective `isolation.level` from the live librdkafka configuration
|
|
1113
1114
|
# and maps it to the numeric isolation level constant. Memoized: the value cannot change
|
|
1114
1115
|
# after client creation.
|
data/lib/rdkafka/defaults.rb
CHANGED
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
module Rdkafka
|
|
4
4
|
# Provides default timeout and configuration values used throughout the library.
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# All timeout values can be overridden per-call via method parameters. These constants provide
|
|
7
|
+
# a central place to understand and reference the default values used across the library.
|
|
8
|
+
#
|
|
9
|
+
# @example Overriding a timeout per-call
|
|
10
|
+
# consumer.committed(timeout_ms: 5_000) # Use 5 seconds instead of default 2 seconds
|
|
11
|
+
#
|
|
12
|
+
# @example Checking the default value
|
|
13
|
+
# Rdkafka::Defaults::CONSUMER_COMMITTED_TIMEOUT_MS # => 2000
|
|
14
|
+
# @note These are rdkafka-ruby defaults, not librdkafka configuration options.
|
|
15
|
+
# For librdkafka options, see:
|
|
16
|
+
# https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md
|
|
8
17
|
module Defaults
|
|
9
18
|
# Consumer timeout for fetching committed offsets
|
|
10
19
|
# @see Consumer#committed
|
data/lib/rdkafka/error.rb
CHANGED
|
@@ -139,7 +139,8 @@ module Rdkafka
|
|
|
139
139
|
# Calls rd_kafka_fatal_error() to get the actual underlying error code and description.
|
|
140
140
|
#
|
|
141
141
|
# @param client_ptr [FFI::Pointer] Pointer to rd_kafka_t client
|
|
142
|
-
# @param fallback_error_code [Integer] Error code to use if no fatal error found
|
|
142
|
+
# @param fallback_error_code [Integer] Error code to use if no fatal error found
|
|
143
|
+
# (default: -150)
|
|
143
144
|
# @param fallback_message [String, nil] Message to use if no fatal error found
|
|
144
145
|
# @param instance_name [String, nil] Optional name of the rdkafka instance
|
|
145
146
|
# @return [RdkafkaError] Error object with fatal flag set to true
|
|
@@ -4,10 +4,14 @@ module Rdkafka
|
|
|
4
4
|
module OAuth
|
|
5
5
|
# Set the OAuthBearer token
|
|
6
6
|
#
|
|
7
|
-
# @param token [String] the mandatory token value to set, often (but not necessarily) a JWS
|
|
8
|
-
#
|
|
7
|
+
# @param token [String] the mandatory token value to set, often (but not necessarily) a JWS
|
|
8
|
+
# compact serialization as per https://tools.ietf.org/html/rfc7515#section-3.1.
|
|
9
|
+
# @param lifetime_ms [Integer] when the token expires, in terms of the number of milliseconds
|
|
10
|
+
# since the epoch. See https://currentmillis.com/.
|
|
9
11
|
# @param principal_name [String] the mandatory Kafka principal name associated with the token.
|
|
10
|
-
# @param extensions [Hash] optional SASL extensions key-value pairs to be communicated to the
|
|
12
|
+
# @param extensions [Hash] optional SASL extensions key-value pairs to be communicated to the
|
|
13
|
+
# broker as additional key-value pairs during the initial client response as per
|
|
14
|
+
# https://tools.ietf.org/html/rfc7628#section-3.1.
|
|
11
15
|
# @return [Integer] 0 on success
|
|
12
16
|
def oauthbearer_set_token(token:, lifetime_ms:, principal_name:, extensions: nil)
|
|
13
17
|
error_buffer = FFI::MemoryPointer.from_string(" " * 256)
|
|
@@ -49,7 +53,8 @@ module Rdkafka
|
|
|
49
53
|
# Convert extensions hash to FFI::MemoryPointer (`const char **`).
|
|
50
54
|
#
|
|
51
55
|
# @param extensions [Hash, nil] extension key-value pairs
|
|
52
|
-
# @return [Array<FFI::MemoryPointer, Array<FFI::MemoryPointer>>] array pointer and string
|
|
56
|
+
# @return [Array<FFI::MemoryPointer, Array<FFI::MemoryPointer>>] array pointer and string
|
|
57
|
+
# pointers
|
|
53
58
|
# @note The returned pointers must be freed manually (autorelease = false).
|
|
54
59
|
def map_extensions(extensions)
|
|
55
60
|
return [nil, nil] if extensions.nil? || extensions.empty?
|
|
@@ -80,7 +85,7 @@ module Rdkafka
|
|
|
80
85
|
#
|
|
81
86
|
# @param extensions [Hash, nil] extension key-value pairs
|
|
82
87
|
# @return [Integer] non-negative even number representing keys + values count
|
|
83
|
-
# @see
|
|
88
|
+
# @see github.com/confluentinc/librdkafka/blob/master/src/rdkafka_sasl_oauthbearer.c#L327-L347
|
|
84
89
|
def extension_size(extensions)
|
|
85
90
|
return 0 unless extensions
|
|
86
91
|
extensions.size * 2
|