karafka-rdkafka 0.21.0-aarch64-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +3 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/workflows/ci_linux_alpine_x86_64_musl.yml +197 -0
  5. data/.github/workflows/ci_linux_alpine_x86_64_musl_complementary.yml +264 -0
  6. data/.github/workflows/ci_linux_debian_x86_64_gnu.yml +271 -0
  7. data/.github/workflows/ci_linux_debian_x86_64_gnu_complementary.yml +334 -0
  8. data/.github/workflows/ci_linux_ubuntu_aarch64_gnu.yml +271 -0
  9. data/.github/workflows/ci_linux_ubuntu_aarch64_gnu_complementary.yml +295 -0
  10. data/.github/workflows/ci_linux_ubuntu_x86_64_gnu.yml +281 -0
  11. data/.github/workflows/ci_linux_ubuntu_x86_64_gnu_complementary.yml +294 -0
  12. data/.github/workflows/ci_macos_arm64.yml +284 -0
  13. data/.github/workflows/push_linux_aarch64_gnu.yml +65 -0
  14. data/.github/workflows/push_linux_x86_64_gnu.yml +65 -0
  15. data/.github/workflows/push_linux_x86_64_musl.yml +79 -0
  16. data/.github/workflows/push_macos_arm64.yml +54 -0
  17. data/.github/workflows/push_ruby.yml +37 -0
  18. data/.github/workflows/trigger-wiki-refresh.yml +30 -0
  19. data/.github/workflows/verify-action-pins.yml +16 -0
  20. data/.gitignore +16 -0
  21. data/.rspec +3 -0
  22. data/.ruby-gemset +1 -0
  23. data/.ruby-version +1 -0
  24. data/.yardopts +2 -0
  25. data/CHANGELOG.md +344 -0
  26. data/Gemfile +5 -0
  27. data/MIT-LICENSE +22 -0
  28. data/README.md +78 -0
  29. data/Rakefile +96 -0
  30. data/dist/cyrus-sasl-2.1.28.tar.gz +0 -0
  31. data/dist/krb5-1.21.3.tar.gz +0 -0
  32. data/dist/openssl-3.0.16.tar.gz +0 -0
  33. data/dist/zlib-1.3.1.tar.gz +0 -0
  34. data/dist/zstd-1.5.7.tar.gz +0 -0
  35. data/docker-compose-ssl.yml +35 -0
  36. data/docker-compose.yml +25 -0
  37. data/ext/README.md +19 -0
  38. data/ext/Rakefile +131 -0
  39. data/ext/build_common.sh +376 -0
  40. data/ext/build_linux_aarch64_gnu.sh +326 -0
  41. data/ext/build_linux_x86_64_gnu.sh +317 -0
  42. data/ext/build_linux_x86_64_musl.sh +773 -0
  43. data/ext/build_macos_arm64.sh +557 -0
  44. data/ext/generate-ssl-certs.sh +109 -0
  45. data/ext/librdkafka.so +0 -0
  46. data/karafka-rdkafka.gemspec +65 -0
  47. data/lib/rdkafka/abstract_handle.rb +116 -0
  48. data/lib/rdkafka/admin/acl_binding_result.rb +51 -0
  49. data/lib/rdkafka/admin/config_binding_result.rb +30 -0
  50. data/lib/rdkafka/admin/config_resource_binding_result.rb +18 -0
  51. data/lib/rdkafka/admin/create_acl_handle.rb +28 -0
  52. data/lib/rdkafka/admin/create_acl_report.rb +24 -0
  53. data/lib/rdkafka/admin/create_partitions_handle.rb +30 -0
  54. data/lib/rdkafka/admin/create_partitions_report.rb +6 -0
  55. data/lib/rdkafka/admin/create_topic_handle.rb +32 -0
  56. data/lib/rdkafka/admin/create_topic_report.rb +24 -0
  57. data/lib/rdkafka/admin/delete_acl_handle.rb +30 -0
  58. data/lib/rdkafka/admin/delete_acl_report.rb +23 -0
  59. data/lib/rdkafka/admin/delete_groups_handle.rb +28 -0
  60. data/lib/rdkafka/admin/delete_groups_report.rb +24 -0
  61. data/lib/rdkafka/admin/delete_topic_handle.rb +32 -0
  62. data/lib/rdkafka/admin/delete_topic_report.rb +24 -0
  63. data/lib/rdkafka/admin/describe_acl_handle.rb +30 -0
  64. data/lib/rdkafka/admin/describe_acl_report.rb +24 -0
  65. data/lib/rdkafka/admin/describe_configs_handle.rb +33 -0
  66. data/lib/rdkafka/admin/describe_configs_report.rb +48 -0
  67. data/lib/rdkafka/admin/incremental_alter_configs_handle.rb +33 -0
  68. data/lib/rdkafka/admin/incremental_alter_configs_report.rb +48 -0
  69. data/lib/rdkafka/admin.rb +832 -0
  70. data/lib/rdkafka/bindings.rb +583 -0
  71. data/lib/rdkafka/callbacks.rb +415 -0
  72. data/lib/rdkafka/config.rb +395 -0
  73. data/lib/rdkafka/consumer/headers.rb +79 -0
  74. data/lib/rdkafka/consumer/message.rb +86 -0
  75. data/lib/rdkafka/consumer/partition.rb +57 -0
  76. data/lib/rdkafka/consumer/topic_partition_list.rb +190 -0
  77. data/lib/rdkafka/consumer.rb +663 -0
  78. data/lib/rdkafka/error.rb +201 -0
  79. data/lib/rdkafka/helpers/oauth.rb +58 -0
  80. data/lib/rdkafka/helpers/time.rb +14 -0
  81. data/lib/rdkafka/metadata.rb +115 -0
  82. data/lib/rdkafka/native_kafka.rb +139 -0
  83. data/lib/rdkafka/producer/delivery_handle.rb +48 -0
  84. data/lib/rdkafka/producer/delivery_report.rb +45 -0
  85. data/lib/rdkafka/producer/partitions_count_cache.rb +216 -0
  86. data/lib/rdkafka/producer.rb +497 -0
  87. data/lib/rdkafka/version.rb +7 -0
  88. data/lib/rdkafka.rb +54 -0
  89. data/renovate.json +92 -0
  90. data/spec/integrations/ssl_stress_spec.rb +121 -0
  91. data/spec/lib/rdkafka/abstract_handle_spec.rb +117 -0
  92. data/spec/lib/rdkafka/admin/create_acl_handle_spec.rb +56 -0
  93. data/spec/lib/rdkafka/admin/create_acl_report_spec.rb +18 -0
  94. data/spec/lib/rdkafka/admin/create_topic_handle_spec.rb +54 -0
  95. data/spec/lib/rdkafka/admin/create_topic_report_spec.rb +16 -0
  96. data/spec/lib/rdkafka/admin/delete_acl_handle_spec.rb +85 -0
  97. data/spec/lib/rdkafka/admin/delete_acl_report_spec.rb +72 -0
  98. data/spec/lib/rdkafka/admin/delete_topic_handle_spec.rb +54 -0
  99. data/spec/lib/rdkafka/admin/delete_topic_report_spec.rb +16 -0
  100. data/spec/lib/rdkafka/admin/describe_acl_handle_spec.rb +85 -0
  101. data/spec/lib/rdkafka/admin/describe_acl_report_spec.rb +73 -0
  102. data/spec/lib/rdkafka/admin_spec.rb +982 -0
  103. data/spec/lib/rdkafka/bindings_spec.rb +198 -0
  104. data/spec/lib/rdkafka/callbacks_spec.rb +20 -0
  105. data/spec/lib/rdkafka/config_spec.rb +258 -0
  106. data/spec/lib/rdkafka/consumer/headers_spec.rb +73 -0
  107. data/spec/lib/rdkafka/consumer/message_spec.rb +139 -0
  108. data/spec/lib/rdkafka/consumer/partition_spec.rb +57 -0
  109. data/spec/lib/rdkafka/consumer/topic_partition_list_spec.rb +248 -0
  110. data/spec/lib/rdkafka/consumer_spec.rb +1343 -0
  111. data/spec/lib/rdkafka/error_spec.rb +95 -0
  112. data/spec/lib/rdkafka/metadata_spec.rb +79 -0
  113. data/spec/lib/rdkafka/native_kafka_spec.rb +130 -0
  114. data/spec/lib/rdkafka/producer/delivery_handle_spec.rb +60 -0
  115. data/spec/lib/rdkafka/producer/delivery_report_spec.rb +25 -0
  116. data/spec/lib/rdkafka/producer/partitions_count_cache_spec.rb +359 -0
  117. data/spec/lib/rdkafka/producer_spec.rb +1527 -0
  118. data/spec/spec_helper.rb +230 -0
  119. metadata +320 -0
@@ -0,0 +1,583 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ # @private
5
+ #
6
+ # @note
7
+ # There are two types of responses related to errors:
8
+ # - rd_kafka_error_t - a C object that we need to remap into an error or null when no error
9
+ # - rd_kafka_resp_err_t - response error code (numeric) that we can use directly
10
+ #
11
+ # It is critical to ensure, that we handle them correctly. The result type should be:
12
+ # - rd_kafka_error_t - :pointer
13
+ # - rd_kafka_resp_err_t - :int
14
+ module Bindings
15
+ extend FFI::Library
16
+
17
+ def self.lib_extension
18
+ if RbConfig::CONFIG['host_os'] =~ /darwin/
19
+ 'dylib'
20
+ else
21
+ 'so'
22
+ end
23
+ end
24
+
25
+ ffi_lib File.join(__dir__, "../../ext/librdkafka.#{lib_extension}")
26
+
27
+ RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS = -175
28
+ RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS = -174
29
+ RD_KAFKA_RESP_ERR__STATE = -172
30
+ RD_KAFKA_RESP_ERR__NOENT = -156
31
+ RD_KAFKA_RESP_ERR_NO_ERROR = 0
32
+
33
+ RD_KAFKA_OFFSET_END = -1
34
+ RD_KAFKA_OFFSET_BEGINNING = -2
35
+ RD_KAFKA_OFFSET_STORED = -1000
36
+ RD_KAFKA_OFFSET_INVALID = -1001
37
+
38
+ EMPTY_HASH = {}.freeze
39
+
40
+ class SizePtr < FFI::Struct
41
+ layout :value, :size_t
42
+ end
43
+
44
+ # This function comes from our patch on top of librdkafka. It allows os to load all the
45
+ # librdkafka components without initializing the client
46
+ # @see https://github.com/confluentinc/librdkafka/issues/4590
47
+ attach_function :rd_kafka_global_init, [], :void
48
+
49
+ # Polling
50
+
51
+ attach_function :rd_kafka_flush, [:pointer, :int], :int, blocking: true
52
+ attach_function :rd_kafka_poll, [:pointer, :int], :int, blocking: true
53
+ attach_function :rd_kafka_outq_len, [:pointer], :int, blocking: true
54
+
55
+ # Metadata
56
+
57
+ attach_function :rd_kafka_name, [:pointer], :string
58
+ attach_function :rd_kafka_memberid, [:pointer], :string, blocking: true
59
+ attach_function :rd_kafka_clusterid, [:pointer], :string, blocking: true
60
+ attach_function :rd_kafka_metadata, [:pointer, :int, :pointer, :pointer, :int], :int, blocking: true
61
+ attach_function :rd_kafka_metadata_destroy, [:pointer], :void, blocking: true
62
+
63
+ # Message struct
64
+
65
+ class Message < FFI::Struct
66
+ layout :err, :int,
67
+ :rkt, :pointer,
68
+ :partition, :int32,
69
+ :payload, :pointer,
70
+ :len, :size_t,
71
+ :key, :pointer,
72
+ :key_len, :size_t,
73
+ :offset, :int64,
74
+ :_private, :pointer
75
+ end
76
+
77
+ attach_function :rd_kafka_message_destroy, [:pointer], :void
78
+ attach_function :rd_kafka_message_timestamp, [:pointer, :pointer], :int64
79
+ attach_function :rd_kafka_topic_new, [:pointer, :string, :pointer], :pointer
80
+ attach_function :rd_kafka_topic_destroy, [:pointer], :pointer
81
+ attach_function :rd_kafka_topic_name, [:pointer], :string
82
+
83
+ # TopicPartition ad TopicPartitionList structs
84
+
85
+ class TopicPartition < FFI::Struct
86
+ layout :topic, :string,
87
+ :partition, :int32,
88
+ :offset, :int64,
89
+ :metadata, :pointer,
90
+ :metadata_size, :size_t,
91
+ :opaque, :pointer,
92
+ :err, :int,
93
+ :_private, :pointer
94
+ end
95
+
96
+ class TopicPartitionList < FFI::Struct
97
+ layout :cnt, :int,
98
+ :size, :int,
99
+ :elems, :pointer
100
+ end
101
+
102
+ attach_function :rd_kafka_topic_partition_list_new, [:int32], :pointer
103
+ attach_function :rd_kafka_topic_partition_list_add, [:pointer, :string, :int32], :pointer
104
+ attach_function :rd_kafka_topic_partition_list_set_offset, [:pointer, :string, :int32, :int64], :void
105
+ attach_function :rd_kafka_topic_partition_list_destroy, [:pointer], :void
106
+ attach_function :rd_kafka_topic_partition_list_copy, [:pointer], :pointer
107
+
108
+ # Configs management
109
+ #
110
+ # Structs for management of configurations
111
+ # Each configuration is attached to a resource and one resource can have many configuration
112
+ # details. Each resource will also have separate errors results if obtaining configuration
113
+ # was not possible for any reason
114
+ class ConfigResource < FFI::Struct
115
+ layout :type, :int,
116
+ :name, :string
117
+ end
118
+
119
+ attach_function :rd_kafka_DescribeConfigs, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
120
+ attach_function :rd_kafka_ConfigResource_new, [:int32, :pointer], :pointer
121
+ attach_function :rd_kafka_ConfigResource_destroy_array, [:pointer, :int32], :void
122
+ attach_function :rd_kafka_event_DescribeConfigs_result, [:pointer], :pointer
123
+ attach_function :rd_kafka_DescribeConfigs_result_resources, [:pointer, :pointer], :pointer
124
+ attach_function :rd_kafka_ConfigResource_configs, [:pointer, :pointer], :pointer
125
+ attach_function :rd_kafka_ConfigEntry_name, [:pointer], :string
126
+ attach_function :rd_kafka_ConfigEntry_value, [:pointer], :string
127
+ attach_function :rd_kafka_ConfigEntry_is_read_only, [:pointer], :int
128
+ attach_function :rd_kafka_ConfigEntry_is_default, [:pointer], :int
129
+ attach_function :rd_kafka_ConfigEntry_is_sensitive, [:pointer], :int
130
+ attach_function :rd_kafka_ConfigEntry_is_synonym, [:pointer], :int
131
+ attach_function :rd_kafka_ConfigEntry_synonyms, [:pointer, :pointer], :pointer
132
+ attach_function :rd_kafka_ConfigResource_error, [:pointer], :int
133
+ attach_function :rd_kafka_ConfigResource_error_string, [:pointer], :string
134
+ attach_function :rd_kafka_IncrementalAlterConfigs, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
135
+ attach_function :rd_kafka_IncrementalAlterConfigs_result_resources, [:pointer, :pointer], :pointer
136
+ attach_function :rd_kafka_ConfigResource_add_incremental_config, [:pointer, :string, :int32, :string], :pointer
137
+ attach_function :rd_kafka_event_IncrementalAlterConfigs_result, [:pointer], :pointer
138
+
139
+ RD_KAFKA_ADMIN_OP_DESCRIBECONFIGS = 5
140
+ RD_KAFKA_EVENT_DESCRIBECONFIGS_RESULT = 104
141
+
142
+ RD_KAFKA_ADMIN_OP_INCREMENTALALTERCONFIGS = 16
143
+ RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT = 131072
144
+
145
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_SET = 0
146
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_DELETE = 1
147
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_APPEND = 2
148
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_SUBTRACT = 3
149
+
150
+ # Errors
151
+ class NativeErrorDesc < FFI::Struct
152
+ layout :code, :int,
153
+ :name, :pointer,
154
+ :desc, :pointer
155
+ end
156
+
157
+ attach_function :rd_kafka_err2name, [:int], :string
158
+ attach_function :rd_kafka_err2str, [:int], :string
159
+ attach_function :rd_kafka_error_is_fatal, [:pointer], :int
160
+ attach_function :rd_kafka_error_is_retriable, [:pointer], :int
161
+ attach_function :rd_kafka_error_txn_requires_abort, [:pointer], :int
162
+ attach_function :rd_kafka_error_destroy, [:pointer], :void
163
+ attach_function :rd_kafka_get_err_descs, [:pointer, :pointer], :void
164
+
165
+ # Configuration
166
+
167
+ enum :kafka_config_response, [
168
+ :config_unknown, -2,
169
+ :config_invalid, -1,
170
+ :config_ok, 0
171
+ ]
172
+
173
+ attach_function :rd_kafka_conf_new, [], :pointer
174
+ attach_function :rd_kafka_conf_set, [:pointer, :string, :string, :pointer, :int], :kafka_config_response
175
+ callback :log_cb, [:pointer, :int, :string, :string], :void
176
+ attach_function :rd_kafka_conf_set_log_cb, [:pointer, :log_cb], :void
177
+ attach_function :rd_kafka_conf_set_opaque, [:pointer, :pointer], :void
178
+ callback :stats_cb, [:pointer, :string, :int, :pointer], :int
179
+ attach_function :rd_kafka_conf_set_stats_cb, [:pointer, :stats_cb], :void
180
+ callback :error_cb, [:pointer, :int, :string, :pointer], :void
181
+ attach_function :rd_kafka_conf_set_error_cb, [:pointer, :error_cb], :void
182
+ attach_function :rd_kafka_rebalance_protocol, [:pointer], :string
183
+ callback :oauthbearer_token_refresh_cb, [:pointer, :string, :pointer], :void
184
+ attach_function :rd_kafka_conf_set_oauthbearer_token_refresh_cb, [:pointer, :oauthbearer_token_refresh_cb], :void
185
+ attach_function :rd_kafka_oauthbearer_set_token, [:pointer, :string, :int64, :pointer, :pointer, :int, :pointer, :int], :int
186
+ attach_function :rd_kafka_oauthbearer_set_token_failure, [:pointer, :string], :int
187
+ # Log queue
188
+ attach_function :rd_kafka_set_log_queue, [:pointer, :pointer], :void
189
+ attach_function :rd_kafka_queue_get_main, [:pointer], :pointer
190
+ # Per topic configs
191
+ attach_function :rd_kafka_topic_conf_new, [], :pointer
192
+ attach_function :rd_kafka_topic_conf_set, [:pointer, :string, :string, :pointer, :int], :kafka_config_response
193
+
194
+ LogCallback = FFI::Function.new(
195
+ :void, [:pointer, :int, :string, :string]
196
+ ) do |_client_ptr, level, _level_string, line|
197
+ severity = case level
198
+ when 0, 1, 2
199
+ Logger::FATAL
200
+ when 3
201
+ Logger::ERROR
202
+ when 4
203
+ Logger::WARN
204
+ when 5, 6
205
+ Logger::INFO
206
+ when 7
207
+ Logger::DEBUG
208
+ else
209
+ Logger::UNKNOWN
210
+ end
211
+
212
+ Rdkafka::Config.ensure_log_thread
213
+ Rdkafka::Config.log_queue << [severity, "rdkafka: #{line}"]
214
+ end
215
+
216
+ StatsCallback = FFI::Function.new(
217
+ :int, [:pointer, :string, :int, :pointer]
218
+ ) do |_client_ptr, json, _json_len, _opaque|
219
+ if Rdkafka::Config.statistics_callback
220
+ stats = JSON.parse(json)
221
+
222
+ # If user requested statistics callbacks, we can use the statistics data to get the
223
+ # partitions count for each topic when this data is published. That way we do not have
224
+ # to query this information when user is using `partition_key`. This takes around 0.02ms
225
+ # every statistics interval period (most likely every 5 seconds) and saves us from making
226
+ # any queries to the cluster for the partition count.
227
+ #
228
+ # One edge case is if user would set the `statistics.interval.ms` much higher than the
229
+ # default current partition count refresh (30 seconds). This is taken care of as the lack
230
+ # of reporting to the partitions cache will cause cache expire and blocking refresh.
231
+ #
232
+ # If user sets `topic.metadata.refresh.interval.ms` too high this is on the user.
233
+ #
234
+ # Since this cache is shared, having few consumers and/or producers in one process will
235
+ # automatically improve the querying times even with low refresh times.
236
+ (stats['topics'] || EMPTY_HASH).each do |topic_name, details|
237
+ partitions_count = details['partitions'].keys.reject { |k| k == '-1' }.size
238
+
239
+ next unless partitions_count.positive?
240
+
241
+ Rdkafka::Producer.partitions_count_cache.set(topic_name, partitions_count)
242
+ end
243
+
244
+ Rdkafka::Config.statistics_callback.call(stats)
245
+ end
246
+
247
+ # Return 0 so librdkafka frees the json string
248
+ 0
249
+ end
250
+
251
+ ErrorCallback = FFI::Function.new(
252
+ :void, [:pointer, :int, :string, :pointer]
253
+ ) do |_client_prr, err_code, reason, _opaque|
254
+ if Rdkafka::Config.error_callback
255
+ error = Rdkafka::RdkafkaError.build(err_code, broker_message: reason)
256
+ error.set_backtrace(caller)
257
+ Rdkafka::Config.error_callback.call(error)
258
+ end
259
+ end
260
+
261
+ # The OAuth callback is currently global and contextless.
262
+ # This means that the callback will be called for all instances, and the callback must be able to determine to which instance it is associated.
263
+ # The instance name will be provided in the callback, allowing the callback to reference the correct instance.
264
+ #
265
+ # An example of how to use the instance name in the callback is given below.
266
+ # The `refresh_token` is configured as the `oauthbearer_token_refresh_callback`.
267
+ # `instances` is a map of client names to client instances, maintained by the user.
268
+ #
269
+ # ```
270
+ # def refresh_token(config, client_name)
271
+ # client = instances[client_name]
272
+ # client.oauthbearer_set_token(
273
+ # token: 'new-token-value',
274
+ # lifetime_ms: token-lifetime-ms,
275
+ # principal_name: 'principal-name'
276
+ # )
277
+ # end
278
+ # ```
279
+ OAuthbearerTokenRefreshCallback = FFI::Function.new(
280
+ :void, [:pointer, :string, :pointer]
281
+ ) do |client_ptr, config, _opaque|
282
+ if Rdkafka::Config.oauthbearer_token_refresh_callback && !client_ptr.null?
283
+ Rdkafka::Config.oauthbearer_token_refresh_callback.call(config, Rdkafka::Bindings.rd_kafka_name(client_ptr))
284
+ end
285
+ end
286
+
287
+ # Handle
288
+
289
+ enum :kafka_type, [
290
+ :rd_kafka_producer,
291
+ :rd_kafka_consumer
292
+ ]
293
+
294
+ attach_function :rd_kafka_new, [:kafka_type, :pointer, :pointer, :int], :pointer
295
+
296
+ attach_function :rd_kafka_destroy, [:pointer], :void
297
+
298
+ # Consumer
299
+
300
+ attach_function :rd_kafka_subscribe, [:pointer, :pointer], :int, blocking: true
301
+ attach_function :rd_kafka_unsubscribe, [:pointer], :int, blocking: true
302
+ attach_function :rd_kafka_subscription, [:pointer, :pointer], :int, blocking: true
303
+ attach_function :rd_kafka_assign, [:pointer, :pointer], :int, blocking: true
304
+ attach_function :rd_kafka_incremental_assign, [:pointer, :pointer], :int, blocking: true
305
+ attach_function :rd_kafka_incremental_unassign, [:pointer, :pointer], :int, blocking: true
306
+ attach_function :rd_kafka_assignment, [:pointer, :pointer], :int, blocking: true
307
+ attach_function :rd_kafka_assignment_lost, [:pointer], :int, blocking: true
308
+ attach_function :rd_kafka_committed, [:pointer, :pointer, :int], :int, blocking: true
309
+ attach_function :rd_kafka_commit, [:pointer, :pointer, :bool], :int, blocking: true
310
+ attach_function :rd_kafka_poll_set_consumer, [:pointer], :void, blocking: true
311
+ attach_function :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: true
312
+ attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
313
+ attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
314
+ attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
315
+ attach_function :rd_kafka_resume_partitions, [:pointer, :pointer], :int, blocking: true
316
+ attach_function :rd_kafka_seek, [:pointer, :int32, :int64, :int], :int, blocking: true
317
+ attach_function :rd_kafka_offsets_for_times, [:pointer, :pointer, :int], :int, blocking: true
318
+ attach_function :rd_kafka_position, [:pointer, :pointer], :int, blocking: true
319
+ # those two are used for eos support
320
+ attach_function :rd_kafka_consumer_group_metadata, [:pointer], :pointer, blocking: true
321
+ attach_function :rd_kafka_consumer_group_metadata_destroy, [:pointer], :void, blocking: true
322
+
323
+ # Headers
324
+ attach_function :rd_kafka_header_get_all, [:pointer, :size_t, :pointer, :pointer, SizePtr], :int
325
+ attach_function :rd_kafka_message_headers, [:pointer, :pointer], :int
326
+
327
+ # Rebalance
328
+
329
+ callback :rebalance_cb_function, [:pointer, :int, :pointer, :pointer], :void
330
+ attach_function :rd_kafka_conf_set_rebalance_cb, [:pointer, :rebalance_cb_function], :void, blocking: true
331
+
332
+ RebalanceCallback = FFI::Function.new(
333
+ :void, [:pointer, :int, :pointer, :pointer]
334
+ ) do |client_ptr, code, partitions_ptr, opaque_ptr|
335
+ case code
336
+ when RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS
337
+ if Rdkafka::Bindings.rd_kafka_rebalance_protocol(client_ptr) == "COOPERATIVE"
338
+ Rdkafka::Bindings.rd_kafka_incremental_assign(client_ptr, partitions_ptr)
339
+ else
340
+ Rdkafka::Bindings.rd_kafka_assign(client_ptr, partitions_ptr)
341
+ end
342
+ else # RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS or errors
343
+ if Rdkafka::Bindings.rd_kafka_rebalance_protocol(client_ptr) == "COOPERATIVE"
344
+ Rdkafka::Bindings.rd_kafka_incremental_unassign(client_ptr, partitions_ptr)
345
+ else
346
+ Rdkafka::Bindings.rd_kafka_assign(client_ptr, FFI::Pointer::NULL)
347
+ end
348
+ end
349
+
350
+ opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
351
+ return unless opaque
352
+
353
+ tpl = Rdkafka::Consumer::TopicPartitionList.from_native_tpl(partitions_ptr).freeze
354
+ begin
355
+ case code
356
+ when RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS
357
+ opaque.call_on_partitions_assigned(tpl)
358
+ when RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS
359
+ opaque.call_on_partitions_revoked(tpl)
360
+ end
361
+ rescue Exception => err
362
+ Rdkafka::Config.logger.error("Unhandled exception: #{err.class} - #{err.message}")
363
+ end
364
+ end
365
+
366
+ # Stats
367
+
368
+ attach_function :rd_kafka_query_watermark_offsets, [:pointer, :string, :int, :pointer, :pointer, :int], :int
369
+
370
+ # Producer
371
+
372
+ RD_KAFKA_VTYPE_END = 0
373
+ RD_KAFKA_VTYPE_TOPIC = 1
374
+ RD_KAFKA_VTYPE_RKT = 2
375
+ RD_KAFKA_VTYPE_PARTITION = 3
376
+ RD_KAFKA_VTYPE_VALUE = 4
377
+ RD_KAFKA_VTYPE_KEY = 5
378
+ RD_KAFKA_VTYPE_OPAQUE = 6
379
+ RD_KAFKA_VTYPE_MSGFLAGS = 7
380
+ RD_KAFKA_VTYPE_TIMESTAMP = 8
381
+ RD_KAFKA_VTYPE_HEADER = 9
382
+ RD_KAFKA_VTYPE_HEADERS = 10
383
+ RD_KAFKA_PURGE_F_QUEUE = 1
384
+ RD_KAFKA_PURGE_F_INFLIGHT = 2
385
+
386
+ RD_KAFKA_MSG_F_COPY = 0x2
387
+
388
+ attach_function :rd_kafka_producev, [:pointer, :varargs], :int, blocking: true
389
+ attach_function :rd_kafka_purge, [:pointer, :int], :int, blocking: true
390
+ callback :delivery_cb, [:pointer, :pointer, :pointer], :void
391
+ attach_function :rd_kafka_conf_set_dr_msg_cb, [:pointer, :delivery_cb], :void
392
+ attach_function :rd_kafka_init_transactions, [:pointer, :int], :pointer, blocking: true
393
+ attach_function :rd_kafka_send_offsets_to_transaction, [:pointer, :pointer, :pointer, :int], :pointer, blocking: true
394
+ attach_function :rd_kafka_begin_transaction, [:pointer], :pointer, blocking: true
395
+ attach_function :rd_kafka_abort_transaction, [:pointer, :int], :pointer, blocking: true
396
+ attach_function :rd_kafka_commit_transaction, [:pointer, :int], :pointer, blocking: true
397
+
398
+ # Partitioner
399
+ PARTITIONERS = %w(random consistent consistent_random murmur2 murmur2_random fnv1a fnv1a_random).each_with_object({}) do |name, hsh|
400
+ method_name = "rd_kafka_msg_partitioner_#{name}".to_sym
401
+ attach_function method_name, [:pointer, :pointer, :size_t, :int32, :pointer, :pointer], :int32
402
+ hsh[name] = method_name
403
+ end
404
+
405
+ def self.partitioner(topic_ptr, str, partition_count, partitioner = "consistent_random")
406
+ # Return RD_KAFKA_PARTITION_UA(unassigned partition) when partition count is nil/zero.
407
+ return -1 unless partition_count&.nonzero?
408
+
409
+ str_ptr = str.empty? ? FFI::MemoryPointer::NULL : FFI::MemoryPointer.from_string(str)
410
+ method_name = PARTITIONERS.fetch(partitioner) do
411
+ raise Rdkafka::Config::ConfigError.new("Unknown partitioner: #{partitioner}")
412
+ end
413
+
414
+ public_send(method_name, topic_ptr, str_ptr, str.size, partition_count, nil, nil)
415
+ end
416
+
417
+ # Create Topics
418
+
419
+ RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
420
+ RD_KAFKA_EVENT_CREATETOPICS_RESULT = 100 # rd_kafka_event_type_t
421
+
422
+ attach_function :rd_kafka_CreateTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
423
+ attach_function :rd_kafka_NewTopic_new, [:pointer, :size_t, :size_t, :pointer, :size_t], :pointer, blocking: true
424
+ attach_function :rd_kafka_NewTopic_set_config, [:pointer, :string, :string], :int32, blocking: true
425
+ attach_function :rd_kafka_NewTopic_destroy, [:pointer], :void, blocking: true
426
+ attach_function :rd_kafka_event_CreateTopics_result, [:pointer], :pointer, blocking: true
427
+ attach_function :rd_kafka_CreateTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
428
+
429
+ # Delete Topics
430
+
431
+ RD_KAFKA_ADMIN_OP_DELETETOPICS = 2 # rd_kafka_admin_op_t
432
+ RD_KAFKA_EVENT_DELETETOPICS_RESULT = 101 # rd_kafka_event_type_t
433
+
434
+ attach_function :rd_kafka_DeleteTopics, [:pointer, :pointer, :size_t, :pointer, :pointer], :int32, blocking: true
435
+ attach_function :rd_kafka_DeleteTopic_new, [:pointer], :pointer, blocking: true
436
+ attach_function :rd_kafka_DeleteTopic_destroy, [:pointer], :void, blocking: true
437
+ attach_function :rd_kafka_event_DeleteTopics_result, [:pointer], :pointer, blocking: true
438
+ attach_function :rd_kafka_DeleteTopics_result_topics, [:pointer, :pointer], :pointer, blocking: true
439
+
440
+ # Create partitions
441
+ RD_KAFKA_ADMIN_OP_CREATEPARTITIONS = 3
442
+ RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT = 102
443
+
444
+ attach_function :rd_kafka_CreatePartitions, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
445
+ attach_function :rd_kafka_NewPartitions_new, %i[pointer size_t pointer size_t], :pointer
446
+ attach_function :rd_kafka_NewPartitions_destroy, [:pointer], :void
447
+ attach_function :rd_kafka_event_CreatePartitions_result, [:pointer], :pointer
448
+ attach_function :rd_kafka_CreatePartitions_result_topics, [:pointer, :pointer], :pointer
449
+
450
+ # Delete Group
451
+
452
+ RD_KAFKA_ADMIN_OP_DELETEGROUPS = 7 # rd_kafka_admin_op_t
453
+ RD_KAFKA_EVENT_DELETEGROUPS_RESULT = 106 # rd_kafka_event_type_t
454
+
455
+ attach_function :rd_kafka_DeleteGroups, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
456
+ attach_function :rd_kafka_DeleteGroup_new, [:pointer], :pointer, blocking: true
457
+ attach_function :rd_kafka_DeleteGroup_destroy, [:pointer], :void, blocking: true
458
+ attach_function :rd_kafka_event_DeleteGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteGroups_result_t*
459
+ attach_function :rd_kafka_DeleteGroups_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteGroups_result_t*, size_t* => rd_kafka_group_result_t**
460
+
461
+ # Background Queue and Callback
462
+
463
+ attach_function :rd_kafka_queue_get_background, [:pointer], :pointer
464
+ attach_function :rd_kafka_conf_set_background_event_cb, [:pointer, :pointer], :void
465
+ attach_function :rd_kafka_queue_destroy, [:pointer], :void
466
+
467
+ # Admin Options
468
+
469
+ attach_function :rd_kafka_AdminOptions_new, [:pointer, :int32], :pointer
470
+ attach_function :rd_kafka_AdminOptions_set_opaque, [:pointer, :pointer], :void
471
+ attach_function :rd_kafka_AdminOptions_destroy, [:pointer], :void
472
+
473
+ # Extracting data from event types
474
+
475
+ attach_function :rd_kafka_event_type, [:pointer], :int32
476
+ attach_function :rd_kafka_event_opaque, [:pointer], :pointer
477
+
478
+ # Extracting data from topic results
479
+
480
+ attach_function :rd_kafka_topic_result_error, [:pointer], :int32
481
+ attach_function :rd_kafka_topic_result_error_string, [:pointer], :pointer
482
+ attach_function :rd_kafka_topic_result_name, [:pointer], :pointer
483
+
484
+ # Create Acls
485
+
486
+ RD_KAFKA_ADMIN_OP_CREATEACLS = 9
487
+ RD_KAFKA_EVENT_CREATEACLS_RESULT = 1024
488
+
489
+ attach_function :rd_kafka_CreateAcls, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
490
+ attach_function :rd_kafka_event_CreateAcls_result, [:pointer], :pointer
491
+ attach_function :rd_kafka_CreateAcls_result_acls, [:pointer, :pointer], :pointer
492
+
493
+ # Delete Acls
494
+
495
+ RD_KAFKA_ADMIN_OP_DELETEACLS = 11
496
+ RD_KAFKA_EVENT_DELETEACLS_RESULT = 4096
497
+
498
+ attach_function :rd_kafka_DeleteAcls, [:pointer, :pointer, :size_t, :pointer, :pointer], :void
499
+ attach_function :rd_kafka_event_DeleteAcls_result, [:pointer], :pointer
500
+ attach_function :rd_kafka_DeleteAcls_result_responses, [:pointer, :pointer], :pointer
501
+ attach_function :rd_kafka_DeleteAcls_result_response_error, [:pointer], :pointer
502
+ attach_function :rd_kafka_DeleteAcls_result_response_matching_acls, [:pointer, :pointer], :pointer
503
+
504
+ # Describe Acls
505
+
506
+ RD_KAFKA_ADMIN_OP_DESCRIBEACLS = 10
507
+ RD_KAFKA_EVENT_DESCRIBEACLS_RESULT = 2048
508
+
509
+ attach_function :rd_kafka_DescribeAcls, [:pointer, :pointer, :pointer, :pointer], :void
510
+ attach_function :rd_kafka_event_DescribeAcls_result, [:pointer], :pointer
511
+ attach_function :rd_kafka_DescribeAcls_result_acls, [:pointer, :pointer], :pointer
512
+
513
+ # Acl Bindings
514
+
515
+ attach_function :rd_kafka_AclBinding_restype, [:pointer], :int32
516
+ attach_function :rd_kafka_AclBinding_name, [:pointer], :pointer
517
+ attach_function :rd_kafka_AclBinding_resource_pattern_type, [:pointer], :int32
518
+ attach_function :rd_kafka_AclBinding_principal, [:pointer], :pointer
519
+ attach_function :rd_kafka_AclBinding_host, [:pointer], :pointer
520
+ attach_function :rd_kafka_AclBinding_operation, [:pointer], :int32
521
+ attach_function :rd_kafka_AclBinding_permission_type, [:pointer], :int32
522
+ attach_function :rd_kafka_AclBinding_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t ], :pointer
523
+ attach_function :rd_kafka_AclBindingFilter_new, [:int32, :pointer, :int32, :pointer, :pointer, :int32, :int32, :pointer, :size_t ], :pointer
524
+ attach_function :rd_kafka_AclBinding_destroy, [:pointer], :void
525
+
526
+ # rd_kafka_ResourceType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7307
527
+
528
+ RD_KAFKA_RESOURCE_ANY = 1
529
+ RD_KAFKA_RESOURCE_TOPIC = 2
530
+ RD_KAFKA_RESOURCE_GROUP = 3
531
+ RD_KAFKA_RESOURCE_BROKER = 4
532
+ RD_KAFKA_RESOURCE_TRANSACTIONAL_ID = 5
533
+
534
+ # rd_kafka_ResourcePatternType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
535
+
536
+ RD_KAFKA_RESOURCE_PATTERN_ANY = 1
537
+ RD_KAFKA_RESOURCE_PATTERN_MATCH = 2
538
+ RD_KAFKA_RESOURCE_PATTERN_LITERAL = 3
539
+ RD_KAFKA_RESOURCE_PATTERN_PREFIXED = 4
540
+
541
+ # rd_kafka_AclOperation_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8403
542
+
543
+ RD_KAFKA_ACL_OPERATION_ANY = 1
544
+ RD_KAFKA_ACL_OPERATION_ALL = 2
545
+ RD_KAFKA_ACL_OPERATION_READ = 3
546
+ RD_KAFKA_ACL_OPERATION_WRITE = 4
547
+ RD_KAFKA_ACL_OPERATION_CREATE = 5
548
+ RD_KAFKA_ACL_OPERATION_DELETE = 6
549
+ RD_KAFKA_ACL_OPERATION_ALTER = 7
550
+ RD_KAFKA_ACL_OPERATION_DESCRIBE = 8
551
+ RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION = 9
552
+ RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS = 10
553
+ RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS = 11
554
+ RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE = 12
555
+
556
+ # rd_kafka_AclPermissionType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L8435
557
+
558
+ RD_KAFKA_ACL_PERMISSION_TYPE_ANY = 1
559
+ RD_KAFKA_ACL_PERMISSION_TYPE_DENY = 2
560
+ RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW = 3
561
+
562
+ # Extracting error details from Acl results
563
+ attach_function :rd_kafka_acl_result_error, [:pointer], :pointer
564
+ attach_function :rd_kafka_error_code, [:pointer], :int32
565
+ attach_function :rd_kafka_error_string, [:pointer], :pointer
566
+ attach_function :rd_kafka_event_error, [:pointer], :int32
567
+ attach_function :rd_kafka_event_error_string, [:pointer], :pointer
568
+ attach_function :rd_kafka_AclBinding_error, [:pointer], :pointer
569
+
570
+
571
+ # Extracting data from group results
572
+ class NativeError < FFI::Struct # rd_kafka_error_t
573
+ layout :code, :int32,
574
+ :errstr, :pointer,
575
+ :fatal, :u_int8_t,
576
+ :retriable, :u_int8_t,
577
+ :txn_requires_abort, :u_int8_t
578
+ end
579
+
580
+ attach_function :rd_kafka_group_result_error, [:pointer], NativeError.by_ref # rd_kafka_group_result_t* => rd_kafka_error_t*
581
+ attach_function :rd_kafka_group_result_name, [:pointer], :pointer
582
+ end
583
+ end