rdkafka 0.30.0 → 0.31.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -2
  3. data/README.md +1 -0
  4. data/dist/{librdkafka-2.15.0.tar.gz → librdkafka-2.15.1.tar.gz} +0 -0
  5. data/docker-compose-ssl.yml +1 -0
  6. data/docker-compose.yml +1 -0
  7. data/lib/rdkafka/admin/describe_cluster_handle.rb +31 -0
  8. data/lib/rdkafka/admin/describe_cluster_report.rb +48 -0
  9. data/lib/rdkafka/admin/describe_consumer_groups_handle.rb +31 -0
  10. data/lib/rdkafka/admin/describe_consumer_groups_report.rb +151 -0
  11. data/lib/rdkafka/admin/describe_result_parsing.rb +47 -0
  12. data/lib/rdkafka/admin/describe_topics_handle.rb +31 -0
  13. data/lib/rdkafka/admin/describe_topics_report.rb +118 -0
  14. data/lib/rdkafka/admin.rb +245 -0
  15. data/lib/rdkafka/bindings/admin/acls.rb +85 -0
  16. data/lib/rdkafka/bindings/admin/configs.rb +37 -0
  17. data/lib/rdkafka/bindings/admin/list_offsets.rb +26 -0
  18. data/lib/rdkafka/bindings/admin.rb +197 -0
  19. data/lib/rdkafka/bindings/callbacks.rb +100 -0
  20. data/lib/rdkafka/bindings/configuration.rb +50 -0
  21. data/lib/rdkafka/bindings/consumer.rb +83 -0
  22. data/lib/rdkafka/bindings/errors.rb +15 -0
  23. data/lib/rdkafka/bindings/handle.rb +16 -0
  24. data/lib/rdkafka/bindings/messages.rb +28 -0
  25. data/lib/rdkafka/bindings/metadata.rb +14 -0
  26. data/lib/rdkafka/bindings/polling.rb +17 -0
  27. data/lib/rdkafka/bindings/producer.rb +77 -0
  28. data/lib/rdkafka/bindings/structs.rb +62 -0
  29. data/lib/rdkafka/bindings.rb +12 -655
  30. data/lib/rdkafka/callbacks/describe_cluster_handler.rb +36 -0
  31. data/lib/rdkafka/callbacks/describe_consumer_groups_handler.rb +36 -0
  32. data/lib/rdkafka/callbacks/describe_topics_handler.rb +36 -0
  33. data/lib/rdkafka/callbacks.rb +10 -1
  34. data/lib/rdkafka/clients.rb +13 -46
  35. data/lib/rdkafka/consumer/message.rb +6 -9
  36. data/lib/rdkafka/producer/delivery_handle.rb +8 -2
  37. data/lib/rdkafka/producer/delivery_report.rb +51 -1
  38. data/lib/rdkafka/version.rb +3 -3
  39. data/lib/rdkafka.rb +10 -0
  40. data/package-lock.json +9 -9
  41. data/rdkafka.gemspec +1 -1
  42. data/renovate.json +3 -0
  43. metadata +27 -3
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ LogCallback = FFI::Function.new(
6
+ :void, [:pointer, :int, :string, :string]
7
+ ) do |_client_ptr, level, _level_string, line|
8
+ severity = case level
9
+ when 0, 1, 2
10
+ Logger::FATAL
11
+ when 3
12
+ Logger::ERROR
13
+ when 4
14
+ Logger::WARN
15
+ when 5, 6
16
+ Logger::INFO
17
+ when 7
18
+ Logger::DEBUG
19
+ else
20
+ Logger::UNKNOWN
21
+ end
22
+
23
+ Rdkafka::Config.ensure_log_thread
24
+ Rdkafka::Config.log_queue << [severity, "rdkafka: #{line}"]
25
+ end
26
+
27
+ StatsCallback = FFI::Function.new(
28
+ :int, [:pointer, :string, :int, :pointer]
29
+ ) do |_client_ptr, json, _json_len, _opaque|
30
+ if Rdkafka::Config.statistics_callback
31
+ stats = JSON.parse(json)
32
+
33
+ # If user requested statistics callbacks, we can use the statistics data to get the
34
+ # partitions count for each topic when this data is published. That way we do not have
35
+ # to query this information when user is using `partition_key`. This takes around 0.02ms
36
+ # every statistics interval period (most likely every 5 seconds) and saves us from making
37
+ # any queries to the cluster for the partition count.
38
+ #
39
+ # One edge case is if user would set the `statistics.interval.ms` much higher than the
40
+ # default current partition count refresh (30 seconds). This is taken care of as the lack
41
+ # of reporting to the partitions cache will cause cache expire and blocking refresh.
42
+ #
43
+ # If user sets `topic.metadata.refresh.interval.ms` too high this is on the user.
44
+ #
45
+ # Since this cache is shared, having few consumers and/or producers in one process will
46
+ # automatically improve the querying times even with low refresh times.
47
+ (stats["topics"] || EMPTY_HASH).each do |topic_name, details|
48
+ partitions_count = details["partitions"].keys.count { |k| !(k == RD_KAFKA_PARTITION_UA_STR) }
49
+
50
+ next unless partitions_count.positive?
51
+
52
+ Rdkafka::Producer.partitions_count_cache.set(topic_name, partitions_count)
53
+ end
54
+
55
+ Rdkafka::Config.statistics_callback.call(stats)
56
+ end
57
+
58
+ # Return 0 so librdkafka frees the json string
59
+ RD_KAFKA_RESP_ERR_NO_ERROR
60
+ end
61
+
62
+ ErrorCallback = FFI::Function.new(
63
+ :void, [:pointer, :int, :string, :pointer]
64
+ ) do |client_ptr, err_code, reason, _opaque|
65
+ if Rdkafka::Config.error_callback
66
+ instance_name = client_ptr.null? ? nil : Rdkafka::Bindings.rd_kafka_name(client_ptr)
67
+ error = Rdkafka::RdkafkaError.new(err_code, broker_message: reason, instance_name: instance_name)
68
+ error.set_backtrace(caller)
69
+ Rdkafka::Config.error_callback.call(error)
70
+ end
71
+ end
72
+
73
+ # The OAuth callback is currently global and contextless. This means that the callback will be
74
+ # called for all instances, and the callback must be able to determine to which instance it is
75
+ # associated. The instance name will be provided in the callback, allowing the callback to
76
+ # reference the correct instance.
77
+ #
78
+ # An example of how to use the instance name in the callback is given below.
79
+ # The `refresh_token` is configured as the `oauthbearer_token_refresh_callback`.
80
+ # `instances` is a map of client names to client instances, maintained by the user.
81
+ #
82
+ # ```
83
+ # def refresh_token(config, client_name)
84
+ # client = instances[client_name]
85
+ # client.oauthbearer_set_token(
86
+ # token: 'new-token-value',
87
+ # lifetime_ms: token-lifetime-ms,
88
+ # principal_name: 'principal-name'
89
+ # )
90
+ # end
91
+ # ```
92
+ OAuthbearerTokenRefreshCallback = FFI::Function.new(
93
+ :void, [:pointer, :string, :pointer]
94
+ ) do |client_ptr, config, _opaque|
95
+ if Rdkafka::Config.oauthbearer_token_refresh_callback && !client_ptr.null?
96
+ Rdkafka::Config.oauthbearer_token_refresh_callback.call(config, Rdkafka::Bindings.rd_kafka_name(client_ptr))
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Configuration
6
+
7
+ enum :kafka_config_response, [
8
+ :config_unknown, -2,
9
+ :config_invalid, -1,
10
+ :config_ok, 0
11
+ ]
12
+
13
+ attach_function :rd_kafka_conf_new, [], :pointer
14
+ attach_function :rd_kafka_conf_set, [:pointer, :string, :string, :pointer, :int], :kafka_config_response
15
+ attach_function :rd_kafka_conf_get, [:pointer, :string, :pointer, :pointer], :kafka_config_response
16
+ attach_function :rd_kafka_conf, [:pointer], :pointer
17
+ attach_function :rd_kafka_conf_dump, [:pointer, :pointer], :pointer
18
+ attach_function :rd_kafka_conf_dump_free, [:pointer, :size_t], :void
19
+ attach_function :rd_kafka_conf_destroy, [:pointer], :void
20
+ callback :log_cb, [:pointer, :int, :string, :string], :void
21
+ attach_function :rd_kafka_conf_set_log_cb, [:pointer, :log_cb], :void
22
+ attach_function :rd_kafka_conf_set_opaque, [:pointer, :pointer], :void
23
+ callback :stats_cb, [:pointer, :string, :int, :pointer], :int
24
+ attach_function :rd_kafka_conf_set_stats_cb, [:pointer, :stats_cb], :void
25
+ callback :error_cb, [:pointer, :int, :string, :pointer], :void
26
+ attach_function :rd_kafka_conf_set_error_cb, [:pointer, :error_cb], :void
27
+ attach_function :rd_kafka_rebalance_protocol, [:pointer], :string
28
+ callback :oauthbearer_token_refresh_cb, [:pointer, :string, :pointer], :void
29
+ attach_function :rd_kafka_conf_set_oauthbearer_token_refresh_cb, [:pointer, :oauthbearer_token_refresh_cb], :void
30
+ attach_function :rd_kafka_oauthbearer_set_token, [:pointer, :string, :int64, :pointer, :pointer, :int, :pointer, :int], :int
31
+ attach_function :rd_kafka_oauthbearer_set_token_failure, [:pointer, :string], :int
32
+ # Log queue
33
+ attach_function :rd_kafka_set_log_queue, [:pointer, :pointer], :void
34
+ attach_function :rd_kafka_queue_get_main, [:pointer], :pointer
35
+ attach_function :rd_kafka_queue_get_background, [:pointer], :pointer
36
+
37
+ # Queue IO Event Support - for fiber scheduler integration
38
+ # Enables notifications to a custom FD when queue transitions from empty to non-empty
39
+ # Arguments:
40
+ # - queue (rd_kafka_queue_t*) - the queue to monitor
41
+ # - fd (int) - file descriptor to write to (provide your own pipe/eventfd)
42
+ # - payload (const void*) - data to write to fd
43
+ # - size (size_t) - size of payload
44
+ attach_function :rd_kafka_queue_io_event_enable, [:pointer, :int, :pointer, :size_t], :void
45
+ # Per topic configs
46
+ attach_function :rd_kafka_topic_conf_new, [], :pointer
47
+ attach_function :rd_kafka_topic_conf_destroy, [:pointer], :void
48
+ attach_function :rd_kafka_topic_conf_set, [:pointer, :string, :string, :pointer, :int], :kafka_config_response
49
+ end
50
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Consumer
6
+
7
+ attach_function :rd_kafka_subscribe, [:pointer, :pointer], :int, blocking: true
8
+ attach_function :rd_kafka_unsubscribe, [:pointer], :int, blocking: true
9
+ attach_function :rd_kafka_subscription, [:pointer, :pointer], :int, blocking: true
10
+ attach_function :rd_kafka_assign, [:pointer, :pointer], :int, blocking: true
11
+ attach_function :rd_kafka_incremental_assign, [:pointer, :pointer], :int, blocking: true
12
+ attach_function :rd_kafka_incremental_unassign, [:pointer, :pointer], :int, blocking: true
13
+ attach_function :rd_kafka_assignment, [:pointer, :pointer], :int, blocking: true
14
+ attach_function :rd_kafka_assignment_lost, [:pointer], :int, blocking: true
15
+ attach_function :rd_kafka_committed, [:pointer, :pointer, :int], :int, blocking: true
16
+ attach_function :rd_kafka_commit, [:pointer, :pointer, :bool], :int, blocking: true
17
+ attach_function :rd_kafka_poll_set_consumer, [:pointer], :void, blocking: true
18
+ attach_function :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: true
19
+ # Non-blocking consumer poll variant (does not release GVL)
20
+ # More efficient for poll(0) calls in fiber schedulers.
21
+ attach_function :rd_kafka_consumer_poll_nb, :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: false
22
+ attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
23
+ attach_function :rd_kafka_queue_get_consumer, [:pointer], :pointer
24
+ attach_function :rd_kafka_consume_batch_queue, [:pointer, :int, :pointer, :size_t], :ssize_t, blocking: true
25
+ attach_function :rd_kafka_consume_batch_queue_nb, :rd_kafka_consume_batch_queue, [:pointer, :int, :pointer, :size_t], :ssize_t, blocking: false
26
+ attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
27
+ attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
28
+ attach_function :rd_kafka_resume_partitions, [:pointer, :pointer], :int, blocking: true
29
+ attach_function :rd_kafka_seek, [:pointer, :int32, :int64, :int], :int, blocking: true
30
+ attach_function :rd_kafka_offsets_for_times, [:pointer, :pointer, :int], :int, blocking: true
31
+ attach_function :rd_kafka_position, [:pointer, :pointer], :int, blocking: true
32
+ # those two are used for eos support
33
+ attach_function :rd_kafka_consumer_group_metadata, [:pointer], :pointer, blocking: true
34
+ attach_function :rd_kafka_consumer_group_metadata_destroy, [:pointer], :void, blocking: true
35
+
36
+ # Headers
37
+ attach_function :rd_kafka_header_get_all, [:pointer, :size_t, :pointer, :pointer, SizePtr], :int
38
+ attach_function :rd_kafka_message_headers, [:pointer, :pointer], :int
39
+
40
+ # Rebalance
41
+
42
+ callback :rebalance_cb_function, [:pointer, :int, :pointer, :pointer], :void
43
+ attach_function :rd_kafka_conf_set_rebalance_cb, [:pointer, :rebalance_cb_function], :void, blocking: true
44
+
45
+ RebalanceCallback = FFI::Function.new(
46
+ :void, [:pointer, :int, :pointer, :pointer]
47
+ ) do |client_ptr, code, partitions_ptr, opaque_ptr|
48
+ case code
49
+ when RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS
50
+ if Rdkafka::Bindings.rd_kafka_rebalance_protocol(client_ptr) == "COOPERATIVE"
51
+ Rdkafka::Bindings.rd_kafka_incremental_assign(client_ptr, partitions_ptr)
52
+ else
53
+ Rdkafka::Bindings.rd_kafka_assign(client_ptr, partitions_ptr)
54
+ end
55
+ else # RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS or errors
56
+ if Rdkafka::Bindings.rd_kafka_rebalance_protocol(client_ptr) == "COOPERATIVE"
57
+ Rdkafka::Bindings.rd_kafka_incremental_unassign(client_ptr, partitions_ptr)
58
+ else
59
+ Rdkafka::Bindings.rd_kafka_assign(client_ptr, FFI::Pointer::NULL)
60
+ end
61
+ end
62
+
63
+ opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
64
+ return unless opaque
65
+
66
+ tpl = Rdkafka::Consumer::TopicPartitionList.from_native_tpl(partitions_ptr).freeze
67
+ begin
68
+ case code
69
+ when RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS
70
+ opaque.call_on_partitions_assigned(tpl)
71
+ when RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS
72
+ opaque.call_on_partitions_revoked(tpl)
73
+ end
74
+ rescue Exception => err
75
+ Rdkafka::Config.logger.error("Unhandled exception: #{err.class} - #{err.message}")
76
+ end
77
+ end
78
+
79
+ # Watermark offsets
80
+
81
+ attach_function :rd_kafka_query_watermark_offsets, [:pointer, :string, :int, :pointer, :pointer, :int], :int, blocking: true
82
+ end
83
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ attach_function :rd_kafka_err2name, [:int], :string
6
+ attach_function :rd_kafka_err2str, [:int], :string
7
+ attach_function :rd_kafka_error_is_fatal, [:pointer], :int
8
+ attach_function :rd_kafka_error_is_retriable, [:pointer], :int
9
+ attach_function :rd_kafka_error_txn_requires_abort, [:pointer], :int
10
+ attach_function :rd_kafka_error_destroy, [:pointer], :void
11
+ attach_function :rd_kafka_error_code, [:pointer], :int32
12
+ attach_function :rd_kafka_error_string, [:pointer], :pointer
13
+ attach_function :rd_kafka_get_err_descs, [:pointer, :pointer], :void
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Handle
6
+
7
+ enum :kafka_type, [
8
+ :rd_kafka_producer,
9
+ :rd_kafka_consumer
10
+ ]
11
+
12
+ attach_function :rd_kafka_new, [:kafka_type, :pointer, :pointer, :int], :pointer
13
+
14
+ attach_function :rd_kafka_destroy, [:pointer], :void
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Messages, topics and topic partition lists
6
+
7
+ attach_function :rd_kafka_message_destroy, [:pointer], :void
8
+ attach_function :rd_kafka_message_timestamp, [:pointer, :pointer], :int64
9
+ attach_function :rd_kafka_message_latency, [:pointer], :int64
10
+ attach_function :rd_kafka_message_broker_id, [:pointer], :int32
11
+ attach_function :rd_kafka_message_status, [:pointer], :int
12
+
13
+ # Message persistence status (rd_kafka_msg_status_t)
14
+ RD_KAFKA_MSG_STATUS_NOT_PERSISTED = 0
15
+ RD_KAFKA_MSG_STATUS_POSSIBLY_PERSISTED = 1
16
+ RD_KAFKA_MSG_STATUS_PERSISTED = 2
17
+
18
+ attach_function :rd_kafka_topic_new, [:pointer, :string, :pointer], :pointer
19
+ attach_function :rd_kafka_topic_destroy, [:pointer], :pointer
20
+ attach_function :rd_kafka_topic_name, [:pointer], :string
21
+
22
+ attach_function :rd_kafka_topic_partition_list_new, [:int32], :pointer
23
+ attach_function :rd_kafka_topic_partition_list_add, [:pointer, :string, :int32], :pointer
24
+ attach_function :rd_kafka_topic_partition_list_set_offset, [:pointer, :string, :int32, :int64], :void
25
+ attach_function :rd_kafka_topic_partition_list_destroy, [:pointer], :void
26
+ attach_function :rd_kafka_topic_partition_list_copy, [:pointer], :pointer
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Metadata
6
+
7
+ attach_function :rd_kafka_name, [:pointer], :string
8
+ attach_function :rd_kafka_memberid, [:pointer], :pointer, blocking: true
9
+ attach_function :rd_kafka_clusterid, [:pointer, :int], :pointer, blocking: true
10
+ attach_function :rd_kafka_mem_free, [:pointer, :pointer], :void
11
+ attach_function :rd_kafka_metadata, [:pointer, :int, :pointer, :pointer, :int], :int, blocking: true
12
+ attach_function :rd_kafka_metadata_destroy, [:pointer], :void, blocking: true
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Polling
6
+
7
+ attach_function :rd_kafka_flush, [:pointer, :int], :int, blocking: true
8
+ attach_function :rd_kafka_poll, [:pointer, :int], :int, blocking: true
9
+ attach_function :rd_kafka_outq_len, [:pointer], :int, blocking: true
10
+
11
+ # Non-blocking poll variants (do not release GVL)
12
+ # These are more efficient for poll(0) calls in fiber schedulers where GVL
13
+ # release/reacquire overhead is wasteful since we don't expect to wait.
14
+ # Uses the same underlying C function but with blocking: false to skip GVL release.
15
+ attach_function :rd_kafka_poll_nb, :rd_kafka_poll, [:pointer, :int], :int, blocking: false
16
+ end
17
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Producer
6
+ RD_KAFKA_VTYPE_END = 0
7
+ RD_KAFKA_VTYPE_TOPIC = 1
8
+ RD_KAFKA_VTYPE_RKT = 2
9
+ RD_KAFKA_VTYPE_PARTITION = 3
10
+ RD_KAFKA_VTYPE_VALUE = 4
11
+ RD_KAFKA_VTYPE_KEY = 5
12
+ RD_KAFKA_VTYPE_OPAQUE = 6
13
+ RD_KAFKA_VTYPE_MSGFLAGS = 7
14
+ RD_KAFKA_VTYPE_TIMESTAMP = 8
15
+ RD_KAFKA_VTYPE_HEADER = 9
16
+ RD_KAFKA_VTYPE_HEADERS = 10
17
+ RD_KAFKA_PURGE_F_QUEUE = 1
18
+ RD_KAFKA_PURGE_F_INFLIGHT = 2
19
+
20
+ RD_KAFKA_MSG_F_COPY = 0x2
21
+
22
+ attach_function :rd_kafka_producev, [:pointer, :varargs], :int, blocking: true
23
+ attach_function :rd_kafka_purge, [:pointer, :int], :int, blocking: true
24
+ callback :delivery_cb, [:pointer, :pointer, :pointer], :void
25
+ attach_function :rd_kafka_conf_set_dr_msg_cb, [:pointer, :delivery_cb], :void
26
+
27
+ # Hash mapping partitioner names to their FFI function symbols
28
+ # @return [Hash{String => Symbol}]
29
+ PARTITIONERS = %w[random consistent consistent_random murmur2 murmur2_random fnv1a fnv1a_random].each_with_object({}) do |name, hsh|
30
+ method_name = :"rd_kafka_msg_partitioner_#{name}"
31
+ attach_function method_name, [:pointer, :pointer, :size_t, :int32, :pointer, :pointer], :int32
32
+ hsh[name] = method_name
33
+ end
34
+
35
+ # Calculates the partition for a message based on the partitioner
36
+ #
37
+ # @param topic_ptr [FFI::Pointer] pointer to the topic handle
38
+ # @param str [String] the partition key string
39
+ # @param partition_count [Integer, nil] number of partitions
40
+ # @param partitioner [String] name of the partitioner to use
41
+ # @return [Integer] partition number or RD_KAFKA_PARTITION_UA if unassigned
42
+ # @raise [Rdkafka::Config::ConfigError] when an unknown partitioner is specified
43
+ def self.partitioner(topic_ptr, str, partition_count, partitioner = "consistent_random")
44
+ # Return RD_KAFKA_PARTITION_UA(unassigned partition) when partition count is nil/zero.
45
+ return RD_KAFKA_PARTITION_UA unless partition_count&.nonzero?
46
+
47
+ str_ptr = str.empty? ? FFI::MemoryPointer::NULL : FFI::MemoryPointer.from_string(str)
48
+ method_name = PARTITIONERS.fetch(partitioner) do
49
+ raise Rdkafka::Config::ConfigError.new("Unknown partitioner: #{partitioner}")
50
+ end
51
+
52
+ public_send(method_name, topic_ptr, str_ptr, partition_key_length(str), partition_count, nil, nil)
53
+ end
54
+
55
+ # Partition key length as the character count (legacy default).
56
+ #
57
+ # @param str [String] the partition key string
58
+ # @return [Integer]
59
+ def self.partition_key_size(str)
60
+ str.size
61
+ end
62
+
63
+ # Partition key length as the byte count, which is what librdkafka hashes (UTF-8 bytes copied
64
+ # into the key pointer) and what other Kafka clients use.
65
+ #
66
+ # @param str [String] the partition key string
67
+ # @return [Integer]
68
+ def self.partition_key_bytesize(str)
69
+ str.bytesize
70
+ end
71
+
72
+ # Length of the partition key passed to librdkafka. Aliased to one of the methods above by
73
+ # `Rdkafka::Config.partitioner_key_uses_bytesize=`, so the per-message path does not check the
74
+ # setting on every call.
75
+ singleton_class.alias_method :partition_key_length, :partition_key_size
76
+ end
77
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # FFI struct representing a Kafka message (rd_kafka_message_t)
6
+ class Message < FFI::Struct
7
+ layout :err, :int,
8
+ :rkt, :pointer,
9
+ :partition, :int32,
10
+ :payload, :pointer,
11
+ :len, :size_t,
12
+ :key, :pointer,
13
+ :key_len, :size_t,
14
+ :offset, :int64,
15
+ :_private, :pointer
16
+ end
17
+
18
+ # FFI struct representing a topic partition (rd_kafka_topic_partition_t)
19
+ class TopicPartition < FFI::Struct
20
+ layout :topic, :string,
21
+ :partition, :int32,
22
+ :offset, :int64,
23
+ :metadata, :pointer,
24
+ :metadata_size, :size_t,
25
+ :opaque, :pointer,
26
+ :err, :int,
27
+ :_private, :pointer
28
+ end
29
+
30
+ # FFI struct representing a topic partition list (rd_kafka_topic_partition_list_t)
31
+ class TopicPartitionList < FFI::Struct
32
+ layout :cnt, :int,
33
+ :size, :int,
34
+ :elems, :pointer
35
+ end
36
+
37
+ # FFI struct representing a config resource (rd_kafka_ConfigResource_t)
38
+ # Structs for management of configurations. Each configuration is attached to a resource
39
+ # and one resource can have many configuration details. Each resource will also have
40
+ # separate errors results if obtaining configuration was not possible for any reason
41
+ class ConfigResource < FFI::Struct
42
+ layout :type, :int,
43
+ :name, :string
44
+ end
45
+
46
+ # FFI struct for error description (rd_kafka_err_desc)
47
+ class NativeErrorDesc < FFI::Struct
48
+ layout :code, :int,
49
+ :name, :pointer,
50
+ :desc, :pointer
51
+ end
52
+
53
+ # FFI struct for native error (rd_kafka_error_t)
54
+ class NativeError < FFI::Struct
55
+ layout :code, :int32,
56
+ :errstr, :pointer,
57
+ :fatal, :u_int8_t,
58
+ :retriable, :u_int8_t,
59
+ :txn_requires_abort, :u_int8_t
60
+ end
61
+ end
62
+ end