karafka-rdkafka 0.14.9 → 0.15.0.alpha1

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.
@@ -16,12 +16,12 @@ describe Rdkafka::Admin do
16
16
  admin.close
17
17
  end
18
18
 
19
- let(:topic_name) { "test-topic-#{Random.new.rand(0..1_000_000)}" }
19
+ let(:topic_name) { "test-topic-#{SecureRandom.uuid}" }
20
20
  let(:topic_partition_count) { 3 }
21
21
  let(:topic_replication_factor) { 1 }
22
22
  let(:topic_config) { {"cleanup.policy" => "compact", "min.cleanable.dirty.ratio" => 0.8} }
23
23
  let(:invalid_topic_config) { {"cleeeeenup.policee" => "campact"} }
24
- let(:group_name) { "test-group-#{Random.new.rand(0..1_000_000)}" }
24
+ let(:group_name) { "test-group-#{SecureRandom.uuid}" }
25
25
 
26
26
  let(:resource_name) {"acl-test-topic"}
27
27
  let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
@@ -129,6 +129,275 @@ describe Rdkafka::Admin do
129
129
  end
130
130
  end
131
131
 
132
+ describe "describe_configs" do
133
+ subject(:resources_results) { admin.describe_configs(resources).wait.resources }
134
+
135
+ before do
136
+ admin.create_topic(topic_name, 2, 1).wait
137
+ sleep(1)
138
+ end
139
+
140
+ context 'when describing config of an existing topic' do
141
+ let(:resources) { [{ resource_type: 2, resource_name: topic_name }] }
142
+
143
+ it do
144
+ expect(resources_results.size).to eq(1)
145
+ expect(resources_results.first.type).to eq(2)
146
+ expect(resources_results.first.name).to eq(topic_name)
147
+ expect(resources_results.first.configs.size).to be > 25
148
+ expect(resources_results.first.configs.first.name).to eq('compression.type')
149
+ expect(resources_results.first.configs.first.value).to eq('producer')
150
+ expect(resources_results.first.configs.map(&:synonyms)).not_to be_empty
151
+ end
152
+ end
153
+
154
+ context 'when describing config of a non-existing topic' do
155
+ let(:resources) { [{ resource_type: 2, resource_name: SecureRandom.uuid }] }
156
+
157
+ it 'expect to raise error' do
158
+ expect { resources_results }.to raise_error(Rdkafka::RdkafkaError, /unknown_topic_or_part/)
159
+ end
160
+ end
161
+
162
+ context 'when describing both existing and non-existing topics' do
163
+ let(:resources) do
164
+ [
165
+ { resource_type: 2, resource_name: topic_name },
166
+ { resource_type: 2, resource_name: SecureRandom.uuid }
167
+ ]
168
+ end
169
+
170
+ it 'expect to raise error' do
171
+ expect { resources_results }.to raise_error(Rdkafka::RdkafkaError, /unknown_topic_or_part/)
172
+ end
173
+ end
174
+
175
+ context 'when describing multiple existing topics' do
176
+ let(:resources) do
177
+ [
178
+ { resource_type: 2, resource_name: 'example_topic' },
179
+ { resource_type: 2, resource_name: topic_name }
180
+ ]
181
+ end
182
+
183
+ it do
184
+ expect(resources_results.size).to eq(2)
185
+ expect(resources_results.first.type).to eq(2)
186
+ expect(resources_results.first.name).to eq('example_topic')
187
+ expect(resources_results.last.type).to eq(2)
188
+ expect(resources_results.last.name).to eq(topic_name)
189
+ end
190
+ end
191
+
192
+ context 'when trying to describe invalid resource type' do
193
+ let(:resources) { [{ resource_type: 0, resource_name: SecureRandom.uuid }] }
194
+
195
+ it 'expect to raise error' do
196
+ expect { resources_results }.to raise_error(Rdkafka::RdkafkaError, /invalid_request/)
197
+ end
198
+ end
199
+
200
+ context 'when trying to describe invalid broker' do
201
+ let(:resources) { [{ resource_type: 4, resource_name: 'non-existing' }] }
202
+
203
+ it 'expect to raise error' do
204
+ expect { resources_results }.to raise_error(Rdkafka::RdkafkaError, /invalid_arg/)
205
+ end
206
+ end
207
+
208
+ context 'when trying to describe valid broker' do
209
+ let(:resources) { [{ resource_type: 4, resource_name: '1' }] }
210
+
211
+ it do
212
+ expect(resources_results.size).to eq(1)
213
+ expect(resources_results.first.type).to eq(4)
214
+ expect(resources_results.first.name).to eq('1')
215
+ expect(resources_results.first.configs.size).to be > 230
216
+ expect(resources_results.first.configs.first.name).to eq('log.cleaner.min.compaction.lag.ms')
217
+ expect(resources_results.first.configs.first.value).to eq('0')
218
+ expect(resources_results.first.configs.map(&:synonyms)).not_to be_empty
219
+ end
220
+ end
221
+
222
+ context 'when describing valid broker with topics in one request' do
223
+ let(:resources) do
224
+ [
225
+ { resource_type: 4, resource_name: '1' },
226
+ { resource_type: 2, resource_name: topic_name }
227
+ ]
228
+ end
229
+
230
+ it do
231
+ expect(resources_results.size).to eq(2)
232
+ expect(resources_results.first.type).to eq(4)
233
+ expect(resources_results.first.name).to eq('1')
234
+ expect(resources_results.first.configs.size).to be > 230
235
+ expect(resources_results.first.configs.first.name).to eq('log.cleaner.min.compaction.lag.ms')
236
+ expect(resources_results.first.configs.first.value).to eq('0')
237
+ expect(resources_results.last.type).to eq(2)
238
+ expect(resources_results.last.name).to eq(topic_name)
239
+ expect(resources_results.last.configs.size).to be > 25
240
+ expect(resources_results.last.configs.first.name).to eq('compression.type')
241
+ expect(resources_results.last.configs.first.value).to eq('producer')
242
+ end
243
+ end
244
+ end
245
+
246
+ describe "incremental_alter_configs" do
247
+ subject(:resources_results) { admin.incremental_alter_configs(resources_with_configs).wait.resources }
248
+
249
+ before do
250
+ admin.create_topic(topic_name, 2, 1).wait
251
+ sleep(1)
252
+ end
253
+
254
+ context 'when altering one topic with one valid config via set' do
255
+ let(:target_retention) { (86400002 + rand(10_000)).to_s }
256
+ let(:resources_with_configs) do
257
+ [
258
+ {
259
+ resource_type: 2,
260
+ resource_name: topic_name,
261
+ configs: [
262
+ {
263
+ name: 'delete.retention.ms',
264
+ value: target_retention,
265
+ op_type: 0
266
+ }
267
+ ]
268
+ }
269
+ ]
270
+ end
271
+
272
+ it do
273
+ expect(resources_results.size).to eq(1)
274
+ expect(resources_results.first.type).to eq(2)
275
+ expect(resources_results.first.name).to eq(topic_name)
276
+
277
+ ret_config = admin.describe_configs(resources_with_configs).wait.resources.first.configs.find do |config|
278
+ config.name == 'delete.retention.ms'
279
+ end
280
+
281
+ expect(ret_config.value).to eq(target_retention)
282
+ end
283
+ end
284
+
285
+ context 'when altering one topic with one valid config via delete' do
286
+ let(:target_retention) { (8640002 + rand(10_000)).to_s }
287
+ let(:resources_with_configs) do
288
+ [
289
+ {
290
+ resource_type: 2,
291
+ resource_name: topic_name,
292
+ configs: [
293
+ {
294
+ name: 'delete.retention.ms',
295
+ value: target_retention,
296
+ op_type: 1
297
+ }
298
+ ]
299
+ }
300
+ ]
301
+ end
302
+
303
+ it do
304
+ expect(resources_results.size).to eq(1)
305
+ expect(resources_results.first.type).to eq(2)
306
+ expect(resources_results.first.name).to eq(topic_name)
307
+ ret_config = admin.describe_configs(resources_with_configs).wait.resources.first.configs.find do |config|
308
+ config.name == 'delete.retention.ms'
309
+ end
310
+
311
+ expect(ret_config.value).to eq('86400000')
312
+ end
313
+ end
314
+
315
+ context 'when altering one topic with one valid config via append' do
316
+ let(:target_policy) { 'compact' }
317
+ let(:resources_with_configs) do
318
+ [
319
+ {
320
+ resource_type: 2,
321
+ resource_name: topic_name,
322
+ configs: [
323
+ {
324
+ name: 'cleanup.policy',
325
+ value: target_policy,
326
+ op_type: 2
327
+ }
328
+ ]
329
+ }
330
+ ]
331
+ end
332
+
333
+ it do
334
+ expect(resources_results.size).to eq(1)
335
+ expect(resources_results.first.type).to eq(2)
336
+ expect(resources_results.first.name).to eq(topic_name)
337
+
338
+ ret_config = admin.describe_configs(resources_with_configs).wait.resources.first.configs.find do |config|
339
+ config.name == 'cleanup.policy'
340
+ end
341
+
342
+ expect(ret_config.value).to eq("delete,#{target_policy}")
343
+ end
344
+ end
345
+
346
+ context 'when altering one topic with one valid config via subtrack' do
347
+ let(:target_policy) { 'delete' }
348
+ let(:resources_with_configs) do
349
+ [
350
+ {
351
+ resource_type: 2,
352
+ resource_name: topic_name,
353
+ configs: [
354
+ {
355
+ name: 'cleanup.policy',
356
+ value: target_policy,
357
+ op_type: 3
358
+ }
359
+ ]
360
+ }
361
+ ]
362
+ end
363
+
364
+ it do
365
+ expect(resources_results.size).to eq(1)
366
+ expect(resources_results.first.type).to eq(2)
367
+ expect(resources_results.first.name).to eq(topic_name)
368
+
369
+ ret_config = admin.describe_configs(resources_with_configs).wait.resources.first.configs.find do |config|
370
+ config.name == 'cleanup.policy'
371
+ end
372
+
373
+ expect(ret_config.value).to eq('')
374
+ end
375
+ end
376
+
377
+ context 'when altering one topic with invalid config' do
378
+ let(:target_retention) { '-10' }
379
+ let(:resources_with_configs) do
380
+ [
381
+ {
382
+ resource_type: 2,
383
+ resource_name: topic_name,
384
+ configs: [
385
+ {
386
+ name: 'delete.retention.ms',
387
+ value: target_retention,
388
+ op_type: 0
389
+ }
390
+ ]
391
+ }
392
+ ]
393
+ end
394
+
395
+ it 'expect to raise error' do
396
+ expect { resources_results }.to raise_error(Rdkafka::RdkafkaError, /invalid_config/)
397
+ end
398
+ end
399
+ end
400
+
132
401
  describe "#delete_topic" do
133
402
  describe "called with invalid input" do
134
403
  # https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/internals/Topic.java#L29
@@ -396,7 +665,10 @@ describe Rdkafka::Admin do
396
665
  end
397
666
 
398
667
  context 'when topic has less then desired number of partitions' do
399
- before { admin.create_topic(topic_name, 1, 1).wait }
668
+ before do
669
+ admin.create_topic(topic_name, 1, 1).wait
670
+ sleep(1)
671
+ end
400
672
 
401
673
  it 'expect to change number of partitions' do
402
674
  admin.create_partitions(topic_name, 10).wait
@@ -22,6 +22,7 @@ describe Rdkafka::Config do
22
22
  it "supports logging queue" do
23
23
  log = StringIO.new
24
24
  Rdkafka::Config.logger = Logger.new(log)
25
+ Rdkafka::Config.ensure_log_thread
25
26
 
26
27
  Rdkafka::Config.log_queue << [Logger::FATAL, "I love testing"]
27
28
  20.times do
@@ -31,6 +32,25 @@ describe Rdkafka::Config do
31
32
 
32
33
  expect(log.string).to include "FATAL -- : I love testing"
33
34
  end
35
+
36
+ it "expect to start new logger thread after fork and work" do
37
+ reader, writer = IO.pipe
38
+
39
+ pid = fork do
40
+ $stdout.reopen(writer)
41
+ Rdkafka::Config.logger = Logger.new($stdout)
42
+ reader.close
43
+ producer = rdkafka_producer_config(debug: 'all').producer
44
+ producer.close
45
+ writer.close
46
+ sleep(1)
47
+ end
48
+
49
+ writer.close
50
+ Process.wait(pid)
51
+ output = reader.read
52
+ expect(output.split("\n").size).to be >= 20
53
+ end
34
54
  end
35
55
 
36
56
  context "statistics callback" do
@@ -211,6 +211,11 @@ describe Rdkafka::Consumer do
211
211
 
212
212
  # 7. ensure same message is read again
213
213
  message2 = consumer.poll(timeout)
214
+
215
+ # This is needed because `enable.auto.offset.store` is true but when running in CI that
216
+ # is overloaded, offset store lags
217
+ sleep(2)
218
+
214
219
  consumer.commit
215
220
  expect(message1.offset).to eq message2.offset
216
221
  expect(message1.payload).to eq message2.payload
data/spec/spec_helper.rb CHANGED
@@ -139,7 +139,7 @@ RSpec.configure do |config|
139
139
  }.each do |topic, partitions|
140
140
  create_topic_handle = admin.create_topic(topic.to_s, partitions, 1)
141
141
  begin
142
- create_topic_handle.wait(max_wait_timeout: 15)
142
+ create_topic_handle.wait(max_wait_timeout: 1.0)
143
143
  rescue Rdkafka::RdkafkaError => ex
144
144
  raise unless ex.message.match?(/topic_already_exists/)
145
145
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,10 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka-rdkafka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.9
4
+ version: 0.15.0.alpha1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thijs Cadier
8
+ - Maciej Mensfeld
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain:
@@ -35,7 +36,7 @@ cert_chain:
35
36
  AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
36
37
  msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
37
38
  -----END CERTIFICATE-----
38
- date: 2024-01-29 00:00:00.000000000 Z
39
+ date: 2024-03-17 00:00:00.000000000 Z
39
40
  dependencies:
40
41
  - !ruby/object:Gem::Dependency
41
42
  name: ffi
@@ -193,6 +194,8 @@ files:
193
194
  - lib/rdkafka/abstract_handle.rb
194
195
  - lib/rdkafka/admin.rb
195
196
  - lib/rdkafka/admin/acl_binding_result.rb
197
+ - lib/rdkafka/admin/config_binding_result.rb
198
+ - lib/rdkafka/admin/config_resource_binding_result.rb
196
199
  - lib/rdkafka/admin/create_acl_handle.rb
197
200
  - lib/rdkafka/admin/create_acl_report.rb
198
201
  - lib/rdkafka/admin/create_partitions_handle.rb
@@ -207,6 +210,10 @@ files:
207
210
  - lib/rdkafka/admin/delete_topic_report.rb
208
211
  - lib/rdkafka/admin/describe_acl_handle.rb
209
212
  - lib/rdkafka/admin/describe_acl_report.rb
213
+ - lib/rdkafka/admin/describe_configs_handle.rb
214
+ - lib/rdkafka/admin/describe_configs_report.rb
215
+ - lib/rdkafka/admin/incremental_alter_configs_handle.rb
216
+ - lib/rdkafka/admin/incremental_alter_configs_report.rb
210
217
  - lib/rdkafka/bindings.rb
211
218
  - lib/rdkafka/callbacks.rb
212
219
  - lib/rdkafka/config.rb
@@ -282,7 +289,7 @@ signing_key:
282
289
  specification_version: 4
283
290
  summary: The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka.
284
291
  It wraps the production-ready C client using the ffi gem and targets Kafka 1.0+
285
- and Ruby 2.4+.
292
+ and Ruby 2.7+.
286
293
  test_files:
287
294
  - spec/rdkafka/abstract_handle_spec.rb
288
295
  - spec/rdkafka/admin/create_acl_handle_spec.rb
metadata.gz.sig CHANGED
Binary file