karafka-rdkafka 0.14.9 → 0.15.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
@@ -97,6 +97,48 @@ module Rdkafka
97
97
  attach_function :rd_kafka_topic_partition_list_destroy, [:pointer], :void
98
98
  attach_function :rd_kafka_topic_partition_list_copy, [:pointer], :pointer
99
99
 
100
+ # Configs management
101
+ #
102
+ # Structs for management of configurations
103
+ # Each configuration is attached to a resource and one resource can have many configuration
104
+ # details. Each resource will also have separate errors results if obtaining configuration
105
+ # was not possible for any reason
106
+ class ConfigResource < FFI::Struct
107
+ layout :type, :int,
108
+ :name, :string
109
+ end
110
+
111
+ attach_function :rd_kafka_DescribeConfigs, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
112
+ attach_function :rd_kafka_ConfigResource_new, [:int32, :pointer], :pointer
113
+ attach_function :rd_kafka_ConfigResource_destroy_array, [:pointer, :int32], :void
114
+ attach_function :rd_kafka_event_DescribeConfigs_result, [:pointer], :pointer
115
+ attach_function :rd_kafka_DescribeConfigs_result_resources, [:pointer, :pointer], :pointer
116
+ attach_function :rd_kafka_ConfigResource_configs, [:pointer, :pointer], :pointer
117
+ attach_function :rd_kafka_ConfigEntry_name, [:pointer], :string
118
+ attach_function :rd_kafka_ConfigEntry_value, [:pointer], :string
119
+ attach_function :rd_kafka_ConfigEntry_is_read_only, [:pointer], :int
120
+ attach_function :rd_kafka_ConfigEntry_is_default, [:pointer], :int
121
+ attach_function :rd_kafka_ConfigEntry_is_sensitive, [:pointer], :int
122
+ attach_function :rd_kafka_ConfigEntry_is_synonym, [:pointer], :int
123
+ attach_function :rd_kafka_ConfigEntry_synonyms, [:pointer, :pointer], :pointer
124
+ attach_function :rd_kafka_ConfigResource_error, [:pointer], :int
125
+ attach_function :rd_kafka_ConfigResource_error_string, [:pointer], :string
126
+ attach_function :rd_kafka_IncrementalAlterConfigs, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
127
+ attach_function :rd_kafka_IncrementalAlterConfigs_result_resources, [:pointer, :pointer], :pointer
128
+ attach_function :rd_kafka_ConfigResource_add_incremental_config, [:pointer, :string, :int32, :string], :pointer
129
+ attach_function :rd_kafka_event_IncrementalAlterConfigs_result, [:pointer], :pointer
130
+
131
+ RD_KAFKA_ADMIN_OP_DESCRIBECONFIGS = 5
132
+ RD_KAFKA_EVENT_DESCRIBECONFIGS_RESULT = 104
133
+
134
+ RD_KAFKA_ADMIN_OP_INCREMENTALALTERCONFIGS = 16
135
+ RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT = 131072
136
+
137
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_SET = 0
138
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_DELETE = 1
139
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_APPEND = 2
140
+ RD_KAFKA_ALTER_CONFIG_OP_TYPE_SUBTRACT = 3
141
+
100
142
  # Errors
101
143
 
102
144
  attach_function :rd_kafka_err2name, [:int], :string
@@ -147,6 +189,8 @@ module Rdkafka
147
189
  else
148
190
  Logger::UNKNOWN
149
191
  end
192
+
193
+ Rdkafka::Config.ensure_log_thread
150
194
  Rdkafka::Config.log_queue << [severity, "rdkafka: #{line}"]
151
195
  end
152
196
 
@@ -113,6 +113,42 @@ module Rdkafka
113
113
  end
114
114
  end
115
115
 
116
+ class DescribeConfigsResult
117
+ attr_reader :result_error, :error_string, :results, :results_count
118
+
119
+ def initialize(event_ptr)
120
+ @results=[]
121
+ @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
122
+ @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
123
+
124
+ if @result_error == 0
125
+ configs_describe_result = Rdkafka::Bindings.rd_kafka_event_DescribeConfigs_result(event_ptr)
126
+ # Get the number of matching acls
127
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
128
+ @results = Rdkafka::Bindings.rd_kafka_DescribeConfigs_result_resources(configs_describe_result, pointer_to_size_t)
129
+ @results_count = pointer_to_size_t.read_int
130
+ end
131
+ end
132
+ end
133
+
134
+ class IncrementalAlterConfigsResult
135
+ attr_reader :result_error, :error_string, :results, :results_count
136
+
137
+ def initialize(event_ptr)
138
+ @results=[]
139
+ @result_error = Rdkafka::Bindings.rd_kafka_event_error(event_ptr)
140
+ @error_string = Rdkafka::Bindings.rd_kafka_event_error_string(event_ptr)
141
+
142
+ if @result_error == 0
143
+ incremental_alter_result = Rdkafka::Bindings.rd_kafka_event_IncrementalAlterConfigs_result(event_ptr)
144
+ # Get the number of matching acls
145
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
146
+ @results = Rdkafka::Bindings.rd_kafka_IncrementalAlterConfigs_result_resources(incremental_alter_result, pointer_to_size_t)
147
+ @results_count = pointer_to_size_t.read_int
148
+ end
149
+ end
150
+ end
151
+
116
152
  # FFI Function used for Create Topic and Delete Topic callbacks
117
153
  BackgroundEventCallbackFunction = FFI::Function.new(
118
154
  :void, [:pointer, :pointer, :pointer]
@@ -123,20 +159,24 @@ module Rdkafka
123
159
  # @private
124
160
  class BackgroundEventCallback
125
161
  def self.call(_, event_ptr, _)
126
- event_type = Rdkafka::Bindings.rd_kafka_event_type(event_ptr)
127
- if event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_CREATETOPICS_RESULT
162
+ case Rdkafka::Bindings.rd_kafka_event_type(event_ptr)
163
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATETOPICS_RESULT
128
164
  process_create_topic(event_ptr)
129
- elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT
165
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBECONFIGS_RESULT
166
+ process_describe_configs(event_ptr)
167
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_INCREMENTALALTERCONFIGS_RESULT
168
+ process_incremental_alter_configs(event_ptr)
169
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT
130
170
  process_delete_topic(event_ptr)
131
- elsif event_type == Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT
171
+ when Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT
132
172
  process_create_partitions(event_ptr)
133
- elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT
173
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT
134
174
  process_create_acl(event_ptr)
135
- elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT
175
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT
136
176
  process_delete_acl(event_ptr)
137
- elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT
177
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_DESCRIBEACLS_RESULT
138
178
  process_describe_acl(event_ptr)
139
- elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT
179
+ when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT
140
180
  process_delete_groups(event_ptr)
141
181
  end
142
182
  end
@@ -156,7 +196,44 @@ module Rdkafka
156
196
  create_topic_handle[:response] = create_topic_results[0].result_error
157
197
  create_topic_handle[:error_string] = create_topic_results[0].error_string
158
198
  create_topic_handle[:result_name] = create_topic_results[0].result_name
159
- create_topic_handle[:pending] = false
199
+
200
+ create_topic_handle.unlock
201
+ end
202
+ end
203
+
204
+ def self.process_describe_configs(event_ptr)
205
+ describe_configs = DescribeConfigsResult.new(event_ptr)
206
+ describe_configs_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
207
+
208
+ if describe_configs_handle = Rdkafka::Admin::DescribeConfigsHandle.remove(describe_configs_handle_ptr.address)
209
+ describe_configs_handle[:response] = describe_configs.result_error
210
+ describe_configs_handle[:response_string] = describe_configs.error_string
211
+ describe_configs_handle[:pending] = false
212
+
213
+ if describe_configs.result_error == 0
214
+ describe_configs_handle[:config_entries] = describe_configs.results
215
+ describe_configs_handle[:entry_count] = describe_configs.results_count
216
+ end
217
+
218
+ describe_configs_handle.unlock
219
+ end
220
+ end
221
+
222
+ def self.process_incremental_alter_configs(event_ptr)
223
+ incremental_alter = IncrementalAlterConfigsResult.new(event_ptr)
224
+ incremental_alter_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
225
+
226
+ if incremental_alter_handle = Rdkafka::Admin::IncrementalAlterConfigsHandle.remove(incremental_alter_handle_ptr.address)
227
+ incremental_alter_handle[:response] = incremental_alter.result_error
228
+ incremental_alter_handle[:response_string] = incremental_alter.error_string
229
+ incremental_alter_handle[:pending] = false
230
+
231
+ if incremental_alter.result_error == 0
232
+ incremental_alter_handle[:config_entries] = incremental_alter.results
233
+ incremental_alter_handle[:entry_count] = incremental_alter.results_count
234
+ end
235
+
236
+ incremental_alter_handle.unlock
160
237
  end
161
238
  end
162
239
 
@@ -173,7 +250,8 @@ module Rdkafka
173
250
  delete_group_handle[:response] = delete_group_results[0].result_error
174
251
  delete_group_handle[:error_string] = delete_group_results[0].error_string
175
252
  delete_group_handle[:result_name] = delete_group_results[0].result_name
176
- delete_group_handle[:pending] = false
253
+
254
+ delete_group_handle.unlock
177
255
  end
178
256
  end
179
257
 
@@ -190,7 +268,8 @@ module Rdkafka
190
268
  delete_topic_handle[:response] = delete_topic_results[0].result_error
191
269
  delete_topic_handle[:error_string] = delete_topic_results[0].error_string
192
270
  delete_topic_handle[:result_name] = delete_topic_results[0].result_name
193
- delete_topic_handle[:pending] = false
271
+
272
+ delete_topic_handle.unlock
194
273
  end
195
274
  end
196
275
 
@@ -207,7 +286,8 @@ module Rdkafka
207
286
  create_partitions_handle[:response] = create_partitions_results[0].result_error
208
287
  create_partitions_handle[:error_string] = create_partitions_results[0].error_string
209
288
  create_partitions_handle[:result_name] = create_partitions_results[0].result_name
210
- create_partitions_handle[:pending] = false
289
+
290
+ create_partitions_handle.unlock
211
291
  end
212
292
  end
213
293
 
@@ -223,7 +303,8 @@ module Rdkafka
223
303
  if create_acl_handle = Rdkafka::Admin::CreateAclHandle.remove(create_acl_handle_ptr.address)
224
304
  create_acl_handle[:response] = create_acl_results[0].result_error
225
305
  create_acl_handle[:response_string] = create_acl_results[0].error_string
226
- create_acl_handle[:pending] = false
306
+
307
+ create_acl_handle.unlock
227
308
  end
228
309
  end
229
310
 
@@ -239,11 +320,13 @@ module Rdkafka
239
320
  if delete_acl_handle = Rdkafka::Admin::DeleteAclHandle.remove(delete_acl_handle_ptr.address)
240
321
  delete_acl_handle[:response] = delete_acl_results[0].result_error
241
322
  delete_acl_handle[:response_string] = delete_acl_results[0].error_string
242
- delete_acl_handle[:pending] = false
323
+
243
324
  if delete_acl_results[0].result_error == 0
244
325
  delete_acl_handle[:matching_acls] = delete_acl_results[0].matching_acls
245
326
  delete_acl_handle[:matching_acls_count] = delete_acl_results[0].matching_acls_count
246
327
  end
328
+
329
+ delete_acl_handle.unlock
247
330
  end
248
331
  end
249
332
 
@@ -254,17 +337,18 @@ module Rdkafka
254
337
  if describe_acl_handle = Rdkafka::Admin::DescribeAclHandle.remove(describe_acl_handle_ptr.address)
255
338
  describe_acl_handle[:response] = describe_acl.result_error
256
339
  describe_acl_handle[:response_string] = describe_acl.error_string
257
- describe_acl_handle[:pending] = false
340
+
258
341
  if describe_acl.result_error == 0
259
- describe_acl_handle[:acls] = describe_acl.matching_acls
342
+ describe_acl_handle[:acls] = describe_acl.matching_acls
260
343
  describe_acl_handle[:acls_count] = describe_acl.matching_acls_count
261
344
  end
345
+
346
+ describe_acl_handle.unlock
262
347
  end
263
348
  end
264
349
  end
265
350
 
266
351
  # FFI Function used for Message Delivery callbacks
267
-
268
352
  DeliveryCallbackFunction = FFI::Function.new(
269
353
  :void, [:pointer, :pointer, :pointer]
270
354
  ) do |client_ptr, message_ptr, opaque_ptr|
@@ -284,7 +368,6 @@ module Rdkafka
284
368
  delivery_handle[:partition] = message[:partition]
285
369
  delivery_handle[:offset] = message[:offset]
286
370
  delivery_handle[:topic_name] = FFI::MemoryPointer.from_string(topic_name)
287
- delivery_handle[:pending] = false
288
371
 
289
372
  # Call delivery callback on opaque
290
373
  if opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
@@ -299,9 +382,10 @@ module Rdkafka
299
382
  delivery_handle
300
383
  )
301
384
  end
385
+
386
+ delivery_handle.unlock
302
387
  end
303
388
  end
304
389
  end
305
-
306
390
  end
307
391
  end
@@ -15,13 +15,12 @@ module Rdkafka
15
15
  @@opaques = ObjectSpace::WeakMap.new
16
16
  # @private
17
17
  @@log_queue = Queue.new
18
-
19
- Thread.start do
20
- loop do
21
- severity, msg = @@log_queue.pop
22
- @@logger.add(severity, msg)
23
- end
24
- end
18
+ # @private
19
+ # We memoize thread on the first log flush
20
+ # This allows us also to restart logger thread on forks
21
+ @@log_thread = nil
22
+ # @private
23
+ @@log_mutex = Mutex.new
25
24
 
26
25
  # Returns the current logger, by default this is a logger to stdout.
27
26
  #
@@ -30,6 +29,24 @@ module Rdkafka
30
29
  @@logger
31
30
  end
32
31
 
32
+ # Makes sure that there is a thread for consuming logs
33
+ # We do not spawn thread immediately and we need to check if it operates to support forking
34
+ def self.ensure_log_thread
35
+ return if @@log_thread && @@log_thread.alive?
36
+
37
+ @@log_mutex.synchronize do
38
+ # Restart if dead (fork, crash)
39
+ @@log_thread = nil if @@log_thread && !@@log_thread.alive?
40
+
41
+ @@log_thread ||= Thread.start do
42
+ loop do
43
+ severity, msg = @@log_queue.pop
44
+ @@logger.add(severity, msg)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
33
50
  # Returns a queue whose contents will be passed to the configured logger. Each entry
34
51
  # should follow the format [Logger::Severity, String]. The benefit over calling the
35
52
  # logger directly is that this is safe to use from trap contexts.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rdkafka
4
- VERSION = "0.14.9"
4
+ VERSION = "0.15.0.alpha1"
5
5
  LIBRDKAFKA_VERSION = "2.3.0"
6
6
  LIBRDKAFKA_SOURCE_SHA256 = "2d49c35c77eeb3d42fa61c43757fcbb6a206daa560247154e60642bcdcc14d12"
7
7
  end
data/lib/rdkafka.rb CHANGED
@@ -23,7 +23,13 @@ require "rdkafka/admin/delete_acl_handle"
23
23
  require "rdkafka/admin/delete_acl_report"
24
24
  require "rdkafka/admin/describe_acl_handle"
25
25
  require "rdkafka/admin/describe_acl_report"
26
+ require "rdkafka/admin/describe_configs_handle"
27
+ require "rdkafka/admin/describe_configs_report"
28
+ require "rdkafka/admin/incremental_alter_configs_handle"
29
+ require "rdkafka/admin/incremental_alter_configs_report"
26
30
  require "rdkafka/admin/acl_binding_result"
31
+ require "rdkafka/admin/config_binding_result"
32
+ require "rdkafka/admin/config_resource_binding_result"
27
33
  require "rdkafka/bindings"
28
34
  require "rdkafka/callbacks"
29
35
  require "rdkafka/config"
@@ -76,37 +76,50 @@ describe Rdkafka::AbstractHandle do
76
76
  end
77
77
 
78
78
  describe "#wait" do
79
- let(:pending_handle) { true }
79
+ context 'when pending_handle true' do
80
+ let(:pending_handle) { true }
80
81
 
81
- it "should wait until the timeout and then raise an error" do
82
- expect {
83
- subject.wait(max_wait_timeout: 0.1)
84
- }.to raise_error Rdkafka::AbstractHandle::WaitTimeoutError, /test_operation/
82
+ it "should wait until the timeout and then raise an error" do
83
+ expect(Kernel).not_to receive(:warn)
84
+ expect {
85
+ subject.wait(max_wait_timeout: 0.1)
86
+ }.to raise_error Rdkafka::AbstractHandle::WaitTimeoutError, /test_operation/
87
+ end
85
88
  end
86
89
 
87
- context "when not pending anymore and no error" do
90
+ context 'when pending_handle false' do
88
91
  let(:pending_handle) { false }
89
- let(:result) { 1 }
90
92
 
91
- it "should return a result" do
92
- wait_result = subject.wait
93
- expect(wait_result).to eq(result)
93
+ it 'should show a deprecation warning when wait_timeout is set' do
94
+ expect(Kernel).to receive(:warn).with(Rdkafka::AbstractHandle::WAIT_TIMEOUT_DEPRECATION_MESSAGE)
95
+ subject.wait(wait_timeout: 0.1)
94
96
  end
95
97
 
96
- it "should wait without a timeout" do
97
- wait_result = subject.wait(max_wait_timeout: nil)
98
- expect(wait_result).to eq(result)
98
+ context "without error" do
99
+ let(:result) { 1 }
100
+
101
+ it "should return a result" do
102
+ expect(Kernel).not_to receive(:warn)
103
+ wait_result = subject.wait
104
+ expect(wait_result).to eq(result)
105
+ end
106
+
107
+ it "should wait without a timeout" do
108
+ expect(Kernel).not_to receive(:warn)
109
+ wait_result = subject.wait(max_wait_timeout: nil)
110
+ expect(wait_result).to eq(result)
111
+ end
99
112
  end
100
- end
101
113
 
102
- context "when not pending anymore and there was an error" do
103
- let(:pending_handle) { false }
104
- let(:response) { 20 }
114
+ context "with error" do
115
+ let(:response) { 20 }
105
116
 
106
- it "should raise an rdkafka error" do
107
- expect {
108
- subject.wait
109
- }.to raise_error Rdkafka::RdkafkaError
117
+ it "should raise an rdkafka error" do
118
+ expect(Kernel).not_to receive(:warn)
119
+ expect {
120
+ subject.wait
121
+ }.to raise_error Rdkafka::RdkafkaError
122
+ end
110
123
  end
111
124
  end
112
125
  end