rdkafka 0.29.2-x86_64-linux-gnu → 0.31.0-x86_64-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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -15
  3. data/README.md +2 -0
  4. data/docker-compose-ssl.yml +1 -0
  5. data/docker-compose.yml +1 -0
  6. data/ext/librdkafka.so +0 -0
  7. data/lib/rdkafka/admin/alter_consumer_group_offsets_handle.rb +31 -0
  8. data/lib/rdkafka/admin/alter_consumer_group_offsets_report.rb +50 -0
  9. data/lib/rdkafka/admin/delete_consumer_group_offsets_handle.rb +31 -0
  10. data/lib/rdkafka/admin/delete_consumer_group_offsets_report.rb +50 -0
  11. data/lib/rdkafka/admin/describe_cluster_handle.rb +31 -0
  12. data/lib/rdkafka/admin/describe_cluster_report.rb +48 -0
  13. data/lib/rdkafka/admin/describe_consumer_groups_handle.rb +31 -0
  14. data/lib/rdkafka/admin/describe_consumer_groups_report.rb +151 -0
  15. data/lib/rdkafka/admin/describe_result_parsing.rb +47 -0
  16. data/lib/rdkafka/admin/describe_topics_handle.rb +31 -0
  17. data/lib/rdkafka/admin/describe_topics_report.rb +118 -0
  18. data/lib/rdkafka/admin.rb +365 -0
  19. data/lib/rdkafka/bindings/admin/acls.rb +85 -0
  20. data/lib/rdkafka/bindings/admin/configs.rb +37 -0
  21. data/lib/rdkafka/bindings/admin/list_offsets.rb +26 -0
  22. data/lib/rdkafka/bindings/admin.rb +197 -0
  23. data/lib/rdkafka/bindings/callbacks.rb +100 -0
  24. data/lib/rdkafka/bindings/configuration.rb +50 -0
  25. data/lib/rdkafka/bindings/consumer.rb +83 -0
  26. data/lib/rdkafka/bindings/errors.rb +15 -0
  27. data/lib/rdkafka/bindings/handle.rb +16 -0
  28. data/lib/rdkafka/bindings/messages.rb +28 -0
  29. data/lib/rdkafka/bindings/metadata.rb +14 -0
  30. data/lib/rdkafka/bindings/polling.rb +17 -0
  31. data/lib/rdkafka/bindings/producer.rb +77 -0
  32. data/lib/rdkafka/bindings/structs.rb +62 -0
  33. data/lib/rdkafka/bindings.rb +12 -612
  34. data/lib/rdkafka/callbacks/alter_consumer_group_offsets_handler.rb +65 -0
  35. data/lib/rdkafka/callbacks/delete_consumer_group_offsets_handler.rb +65 -0
  36. data/lib/rdkafka/callbacks/describe_cluster_handler.rb +36 -0
  37. data/lib/rdkafka/callbacks/describe_consumer_groups_handler.rb +36 -0
  38. data/lib/rdkafka/callbacks/describe_topics_handler.rb +36 -0
  39. data/lib/rdkafka/callbacks.rb +24 -17
  40. data/lib/rdkafka/clients.rb +13 -46
  41. data/lib/rdkafka/config.rb +34 -0
  42. data/lib/rdkafka/consumer/message.rb +6 -9
  43. data/lib/rdkafka/producer/delivery_handle.rb +8 -2
  44. data/lib/rdkafka/producer/delivery_report.rb +51 -1
  45. data/lib/rdkafka/version.rb +3 -3
  46. data/lib/rdkafka.rb +16 -0
  47. data/package-lock.json +9 -9
  48. data/rdkafka.gemspec +1 -1
  49. data/renovate.json +3 -0
  50. metadata +33 -3
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ module Bindings
5
+ # Create Topics
6
+ RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
7
+ RD_KAFKA_EVENT_CREATETOPICS_RESULT = 100 # rd_kafka_event_type_t
8
+
9
+ attach_function :rd_kafka_CreateTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
10
+ attach_function :rd_kafka_NewTopic_new, [:pointer, :size_t, :size_t, :pointer, :size_t], :pointer, blocking: true
11
+ attach_function :rd_kafka_NewTopic_set_config, [:pointer, :string, :string], :int32, blocking: true
12
+ attach_function :rd_kafka_NewTopic_destroy, [:pointer], :void, blocking: true
13
+ attach_function :rd_kafka_event_CreateTopics_result, [:pointer], :pointer, blocking: true
14
+ attach_function :rd_kafka_CreateTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
15
+
16
+ # Delete Topics
17
+ RD_KAFKA_ADMIN_OP_DELETETOPICS = 2 # rd_kafka_admin_op_t
18
+ RD_KAFKA_EVENT_DELETETOPICS_RESULT = 101 # rd_kafka_event_type_t
19
+
20
+ attach_function :rd_kafka_DeleteTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :int32, blocking: true
21
+ attach_function :rd_kafka_DeleteTopic_new, [:pointer], :pointer, blocking: true
22
+ attach_function :rd_kafka_DeleteTopic_destroy, [:pointer], :void, blocking: true
23
+ attach_function :rd_kafka_event_DeleteTopics_result, [:pointer], :pointer, blocking: true
24
+ attach_function :rd_kafka_DeleteTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
25
+
26
+ # Create partitions
27
+ RD_KAFKA_ADMIN_OP_CREATEPARTITIONS = 3
28
+ RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT = 102
29
+
30
+ attach_function :rd_kafka_CreatePartitions, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
31
+ attach_function :rd_kafka_NewPartitions_new, %i[pointer size_t pointer size_t], :pointer
32
+ attach_function :rd_kafka_NewPartitions_destroy, [:pointer], :void
33
+ attach_function :rd_kafka_event_CreatePartitions_result, [:pointer], :pointer
34
+ attach_function :rd_kafka_CreatePartitions_result_topics, [:pointer, :pointer], :pointer
35
+
36
+ # Delete Group
37
+ RD_KAFKA_ADMIN_OP_DELETEGROUPS = 7 # rd_kafka_admin_op_t
38
+ RD_KAFKA_EVENT_DELETEGROUPS_RESULT = 106 # rd_kafka_event_type_t
39
+
40
+ attach_function :rd_kafka_DeleteGroups, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
41
+ attach_function :rd_kafka_DeleteGroup_new, [:pointer], :pointer, blocking: true
42
+ attach_function :rd_kafka_DeleteGroup_destroy, [:pointer], :void, blocking: true
43
+ attach_function :rd_kafka_event_DeleteGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteGroups_result_t*
44
+ attach_function :rd_kafka_DeleteGroups_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteGroups_result_t*, size_t* => rd_kafka_group_result_t**
45
+
46
+ # Alter Consumer Group Offsets
47
+ RD_KAFKA_ADMIN_OP_ALTERCONSUMERGROUPOFFSETS = 15 # rd_kafka_admin_op_t
48
+ RD_KAFKA_EVENT_ALTERCONSUMERGROUPOFFSETS_RESULT = 0x10000 # rd_kafka_event_type_t
49
+
50
+ attach_function :rd_kafka_AlterConsumerGroupOffsets, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
51
+ attach_function :rd_kafka_AlterConsumerGroupOffsets_new, [:pointer, :pointer], :pointer, blocking: true # const char*, const rd_kafka_topic_partition_list_t* => rd_kafka_AlterConsumerGroupOffsets_t*
52
+ attach_function :rd_kafka_AlterConsumerGroupOffsets_destroy, [:pointer], :void, blocking: true
53
+ attach_function :rd_kafka_event_AlterConsumerGroupOffsets_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_AlterConsumerGroupOffsets_result_t*
54
+ attach_function :rd_kafka_AlterConsumerGroupOffsets_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_AlterConsumerGroupOffsets_result_t*, size_t* => rd_kafka_group_result_t**
55
+
56
+ # Delete Consumer Group Offsets
57
+ RD_KAFKA_ADMIN_OP_DELETECONSUMERGROUPOFFSETS = 8 # rd_kafka_admin_op_t
58
+ RD_KAFKA_EVENT_DELETECONSUMERGROUPOFFSETS_RESULT = 107 # rd_kafka_event_type_t
59
+
60
+ attach_function :rd_kafka_DeleteConsumerGroupOffsets, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
61
+ attach_function :rd_kafka_DeleteConsumerGroupOffsets_new, [:pointer, :pointer], :pointer, blocking: true # const char*, const rd_kafka_topic_partition_list_t* => rd_kafka_DeleteConsumerGroupOffsets_t*
62
+ attach_function :rd_kafka_DeleteConsumerGroupOffsets_destroy, [:pointer], :void, blocking: true
63
+ attach_function :rd_kafka_event_DeleteConsumerGroupOffsets_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteConsumerGroupOffsets_result_t*
64
+ attach_function :rd_kafka_DeleteConsumerGroupOffsets_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteConsumerGroupOffsets_result_t*, size_t* => rd_kafka_group_result_t**
65
+
66
+ # Delete Records
67
+ RD_KAFKA_ADMIN_OP_DELETERECORDS = 6 # rd_kafka_admin_op_t
68
+ RD_KAFKA_EVENT_DELETERECORDS_RESULT = 105 # rd_kafka_event_type_t
69
+
70
+ attach_function :rd_kafka_DeleteRecords, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
71
+ attach_function :rd_kafka_DeleteRecords_new, [:pointer], :pointer, blocking: true
72
+ attach_function :rd_kafka_DeleteRecords_destroy, [:pointer], :void, blocking: true
73
+ attach_function :rd_kafka_event_DeleteRecords_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteRecords_result_t*
74
+ attach_function :rd_kafka_DeleteRecords_result_offsets, [:pointer], :pointer, blocking: true # rd_kafka_DeleteRecords_result_t* => rd_kafka_topic_partition_list_t*
75
+
76
+ # List Consumer Groups
77
+ RD_KAFKA_ADMIN_OP_LISTCONSUMERGROUPS = 12 # rd_kafka_admin_op_t
78
+ RD_KAFKA_EVENT_LISTCONSUMERGROUPS_RESULT = 0x2000 # rd_kafka_event_type_t
79
+
80
+ # Consumer group states (rd_kafka_consumer_group_state_t)
81
+ RD_KAFKA_CONSUMER_GROUP_STATE_UNKNOWN = 0
82
+ RD_KAFKA_CONSUMER_GROUP_STATE_PREPARING_REBALANCE = 1
83
+ RD_KAFKA_CONSUMER_GROUP_STATE_COMPLETING_REBALANCE = 2
84
+ RD_KAFKA_CONSUMER_GROUP_STATE_STABLE = 3
85
+ RD_KAFKA_CONSUMER_GROUP_STATE_DEAD = 4
86
+ RD_KAFKA_CONSUMER_GROUP_STATE_EMPTY = 5
87
+
88
+ attach_function :rd_kafka_ListConsumerGroups, [:pointer, :pointer, :pointer], :void, blocking: true
89
+ attach_function :rd_kafka_event_ListConsumerGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_ListConsumerGroups_result_t*
90
+ attach_function :rd_kafka_ListConsumerGroups_result_valid, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_ConsumerGroupListing_t**
91
+ attach_function :rd_kafka_ListConsumerGroups_result_errors, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_error_t**
92
+ attach_function :rd_kafka_ConsumerGroupListing_group_id, [:pointer], :pointer, blocking: true # => const char*
93
+ attach_function :rd_kafka_ConsumerGroupListing_is_simple_consumer_group, [:pointer], :int, blocking: true
94
+ attach_function :rd_kafka_ConsumerGroupListing_state, [:pointer], :int, blocking: true
95
+ attach_function :rd_kafka_consumer_group_state_name, [:int], :pointer, blocking: true # => const char*
96
+
97
+ # Describe Consumer Groups
98
+ RD_KAFKA_ADMIN_OP_DESCRIBECONSUMERGROUPS = 13 # rd_kafka_admin_op_t
99
+ RD_KAFKA_EVENT_DESCRIBECONSUMERGROUPS_RESULT = 0x4000 # rd_kafka_event_type_t
100
+
101
+ # Consumer group types (rd_kafka_consumer_group_type_t)
102
+ RD_KAFKA_CONSUMER_GROUP_TYPE_UNKNOWN = 0
103
+ RD_KAFKA_CONSUMER_GROUP_TYPE_CONSUMER = 1
104
+ RD_KAFKA_CONSUMER_GROUP_TYPE_CLASSIC = 2
105
+
106
+ attach_function :rd_kafka_DescribeConsumerGroups, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
107
+ attach_function :rd_kafka_event_DescribeConsumerGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DescribeConsumerGroups_result_t*
108
+ attach_function :rd_kafka_DescribeConsumerGroups_result_groups, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_ConsumerGroupDescription_t**
109
+ attach_function :rd_kafka_ConsumerGroupDescription_group_id, [:pointer], :pointer, blocking: true # => const char*
110
+ attach_function :rd_kafka_ConsumerGroupDescription_error, [:pointer], :pointer, blocking: true # => const rd_kafka_error_t*
111
+ attach_function :rd_kafka_ConsumerGroupDescription_is_simple_consumer_group, [:pointer], :int, blocking: true
112
+ attach_function :rd_kafka_ConsumerGroupDescription_partition_assignor, [:pointer], :pointer, blocking: true # => const char*
113
+ attach_function :rd_kafka_ConsumerGroupDescription_state, [:pointer], :int, blocking: true
114
+ attach_function :rd_kafka_ConsumerGroupDescription_type, [:pointer], :int, blocking: true
115
+ attach_function :rd_kafka_ConsumerGroupDescription_authorized_operations, [:pointer, :pointer], :pointer, blocking: true # grpdesc*, size_t* => const rd_kafka_AclOperation_t*
116
+ attach_function :rd_kafka_ConsumerGroupDescription_coordinator, [:pointer], :pointer, blocking: true # => const rd_kafka_Node_t*
117
+ attach_function :rd_kafka_ConsumerGroupDescription_member_count, [:pointer], :size_t, blocking: true
118
+ attach_function :rd_kafka_ConsumerGroupDescription_member, [:pointer, :size_t], :pointer, blocking: true # => const rd_kafka_MemberDescription_t*
119
+ attach_function :rd_kafka_MemberDescription_client_id, [:pointer], :pointer, blocking: true # => const char*
120
+ attach_function :rd_kafka_MemberDescription_group_instance_id, [:pointer], :pointer, blocking: true # => const char*
121
+ attach_function :rd_kafka_MemberDescription_consumer_id, [:pointer], :pointer, blocking: true # => const char*
122
+ attach_function :rd_kafka_MemberDescription_host, [:pointer], :pointer, blocking: true # => const char*
123
+ attach_function :rd_kafka_MemberDescription_assignment, [:pointer], :pointer, blocking: true # => const rd_kafka_MemberAssignment_t*
124
+ attach_function :rd_kafka_MemberDescription_target_assignment, [:pointer], :pointer, blocking: true # => const rd_kafka_MemberAssignment_t*
125
+ attach_function :rd_kafka_MemberAssignment_partitions, [:pointer], :pointer, blocking: true # => const rd_kafka_topic_partition_list_t*
126
+ attach_function :rd_kafka_consumer_group_type_name, [:int], :pointer, blocking: true # => const char*
127
+
128
+ # Describe Topics and Describe Cluster
129
+ RD_KAFKA_ADMIN_OP_DESCRIBETOPICS = 19 # rd_kafka_admin_op_t
130
+ RD_KAFKA_EVENT_DESCRIBETOPICS_RESULT = 0x100000 # rd_kafka_event_type_t
131
+ RD_KAFKA_ADMIN_OP_DESCRIBECLUSTER = 20 # rd_kafka_admin_op_t
132
+ RD_KAFKA_EVENT_DESCRIBECLUSTER_RESULT = 0x200000 # rd_kafka_event_type_t
133
+
134
+ attach_function :rd_kafka_AdminOptions_set_include_authorized_operations, [:pointer, :int], :pointer, blocking: true # => rd_kafka_error_t*
135
+ attach_function :rd_kafka_TopicCollection_of_topic_names, [:pointer, :size_t], :pointer, blocking: true # const char**, size_t => rd_kafka_TopicCollection_t*
136
+ attach_function :rd_kafka_TopicCollection_destroy, [:pointer], :void, blocking: true
137
+ attach_function :rd_kafka_DescribeTopics, [:pointer, :pointer, :pointer, :pointer], :void, blocking: true
138
+ attach_function :rd_kafka_event_DescribeTopics_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DescribeTopics_result_t*
139
+ attach_function :rd_kafka_DescribeTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_TopicDescription_t**
140
+ attach_function :rd_kafka_TopicDescription_name, [:pointer], :pointer, blocking: true # => const char*
141
+ attach_function :rd_kafka_TopicDescription_topic_id, [:pointer], :pointer, blocking: true # => rd_kafka_Uuid_t*
142
+ attach_function :rd_kafka_TopicDescription_is_internal, [:pointer], :int, blocking: true
143
+ attach_function :rd_kafka_TopicDescription_partitions, [:pointer, :pointer], :pointer, blocking: true # desc*, size_t* => rd_kafka_TopicPartitionInfo_t**
144
+ attach_function :rd_kafka_TopicDescription_authorized_operations, [:pointer, :pointer], :pointer, blocking: true # desc*, size_t* => rd_kafka_AclOperation_t*
145
+ attach_function :rd_kafka_TopicDescription_error, [:pointer], :pointer, blocking: true # => rd_kafka_error_t*
146
+ attach_function :rd_kafka_TopicPartitionInfo_partition, [:pointer], :int, blocking: true
147
+ attach_function :rd_kafka_TopicPartitionInfo_leader, [:pointer], :pointer, blocking: true # => rd_kafka_Node_t*
148
+ attach_function :rd_kafka_TopicPartitionInfo_replicas, [:pointer, :pointer], :pointer, blocking: true # info*, size_t* => rd_kafka_Node_t**
149
+ attach_function :rd_kafka_TopicPartitionInfo_isr, [:pointer, :pointer], :pointer, blocking: true # info*, size_t* => rd_kafka_Node_t**
150
+ attach_function :rd_kafka_Uuid_base64str, [:pointer], :pointer, blocking: true # => const char*
151
+ attach_function :rd_kafka_Uuid_most_significant_bits, [:pointer], :int64, blocking: true
152
+ attach_function :rd_kafka_Uuid_least_significant_bits, [:pointer], :int64, blocking: true
153
+ attach_function :rd_kafka_DescribeCluster, [:pointer, :pointer, :pointer], :void, blocking: true
154
+ attach_function :rd_kafka_event_DescribeCluster_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DescribeCluster_result_t*
155
+ attach_function :rd_kafka_DescribeCluster_result_nodes, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_Node_t**
156
+ attach_function :rd_kafka_DescribeCluster_result_controller, [:pointer], :pointer, blocking: true # => rd_kafka_Node_t*
157
+ attach_function :rd_kafka_DescribeCluster_result_cluster_id, [:pointer], :pointer, blocking: true # => const char*
158
+ attach_function :rd_kafka_DescribeCluster_result_authorized_operations, [:pointer, :pointer], :pointer, blocking: true # result*, size_t* => rd_kafka_AclOperation_t*
159
+ attach_function :rd_kafka_Node_id, [:pointer], :int, blocking: true
160
+ attach_function :rd_kafka_Node_host, [:pointer], :pointer, blocking: true # => const char*
161
+ attach_function :rd_kafka_Node_port, [:pointer], :uint16, blocking: true
162
+ attach_function :rd_kafka_Node_rack, [:pointer], :pointer, blocking: true # => const char*
163
+
164
+ # Background Queue and Callback
165
+
166
+ attach_function :rd_kafka_conf_set_background_event_cb, [:pointer, :pointer], :void
167
+ attach_function :rd_kafka_queue_destroy, [:pointer], :void
168
+
169
+ # Admin Options
170
+
171
+ attach_function :rd_kafka_AdminOptions_new, [:pointer, :int32], :pointer
172
+ attach_function :rd_kafka_AdminOptions_set_opaque, [:pointer, :pointer], :void
173
+ attach_function :rd_kafka_AdminOptions_destroy, [:pointer], :void
174
+
175
+ # Extracting data from event types
176
+
177
+ attach_function :rd_kafka_event_type, [:pointer], :int32
178
+ attach_function :rd_kafka_event_opaque, [:pointer], :pointer
179
+ attach_function :rd_kafka_event_destroy, [:pointer], :void
180
+ attach_function :rd_kafka_event_error, [:pointer], :int32
181
+ attach_function :rd_kafka_event_error_string, [:pointer], :pointer
182
+
183
+ # Extracting data from topic results
184
+
185
+ attach_function :rd_kafka_topic_result_error, [:pointer], :int32
186
+ attach_function :rd_kafka_topic_result_error_string, [:pointer], :pointer
187
+ attach_function :rd_kafka_topic_result_name, [:pointer], :pointer
188
+
189
+ attach_function :rd_kafka_group_result_error, [:pointer], NativeError.by_ref # rd_kafka_group_result_t* => rd_kafka_error_t*
190
+ attach_function :rd_kafka_group_result_name, [:pointer], :pointer
191
+ attach_function :rd_kafka_group_result_partitions, [:pointer], :pointer # rd_kafka_group_result_t* => rd_kafka_topic_partition_list_t*
192
+ end
193
+ end
194
+
195
+ require_relative "admin/configs"
196
+ require_relative "admin/list_offsets"
197
+ require_relative "admin/acls"
@@ -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