rdkafka 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.semaphore/semaphore.yml +1 -1
- data/CHANGELOG.md +9 -1
- data/Guardfile +19 -0
- data/README.md +3 -1
- data/bin/console +11 -0
- data/docker-compose.yml +3 -3
- data/ext/README.md +1 -1
- data/ext/Rakefile +3 -19
- data/lib/rdkafka/admin.rb +2 -2
- data/lib/rdkafka/bindings.rb +10 -3
- data/lib/rdkafka/callbacks.rb +1 -1
- data/lib/rdkafka/config.rb +3 -3
- data/lib/rdkafka/consumer.rb +3 -3
- data/lib/rdkafka/producer/client.rb +47 -0
- data/lib/rdkafka/producer/delivery_report.rb +1 -1
- data/lib/rdkafka/producer.rb +32 -35
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +1 -0
- data/rdkafka.gemspec +9 -7
- data/spec/rdkafka/abstract_handle_spec.rb +0 -1
- data/spec/rdkafka/admin_spec.rb +1 -1
- data/spec/rdkafka/bindings_spec.rb +7 -0
- data/spec/rdkafka/config_spec.rb +2 -2
- data/spec/rdkafka/consumer_spec.rb +67 -49
- data/spec/rdkafka/metadata_spec.rb +1 -1
- data/spec/rdkafka/producer/client_spec.rb +145 -0
- data/spec/rdkafka/producer_spec.rb +56 -8
- data/spec/spec_helper.rb +50 -9
- metadata +63 -28
@@ -3,9 +3,8 @@ require "ostruct"
|
|
3
3
|
require 'securerandom'
|
4
4
|
|
5
5
|
describe Rdkafka::Consumer do
|
6
|
-
let(:
|
7
|
-
let(:
|
8
|
-
let(:producer) { config.producer }
|
6
|
+
let(:consumer) { rdkafka_consumer_config.consumer }
|
7
|
+
let(:producer) { rdkafka_producer_config.producer }
|
9
8
|
|
10
9
|
after { consumer.close }
|
11
10
|
after { producer.close }
|
@@ -242,7 +241,7 @@ describe Rdkafka::Consumer do
|
|
242
241
|
|
243
242
|
it "should return the assignment when subscribed" do
|
244
243
|
# Make sure there's a message
|
245
|
-
|
244
|
+
producer.produce(
|
246
245
|
topic: "consume_test_topic",
|
247
246
|
payload: "payload 1",
|
248
247
|
key: "key 1",
|
@@ -273,7 +272,7 @@ describe Rdkafka::Consumer do
|
|
273
272
|
it "should close a consumer" do
|
274
273
|
consumer.subscribe("consume_test_topic")
|
275
274
|
100.times do |i|
|
276
|
-
|
275
|
+
producer.produce(
|
277
276
|
topic: "consume_test_topic",
|
278
277
|
payload: "payload #{i}",
|
279
278
|
key: "key #{i}",
|
@@ -290,7 +289,7 @@ describe Rdkafka::Consumer do
|
|
290
289
|
describe "#commit, #committed and #store_offset" do
|
291
290
|
# Make sure there's a stored offset
|
292
291
|
let!(:report) do
|
293
|
-
|
292
|
+
producer.produce(
|
294
293
|
topic: "consume_test_topic",
|
295
294
|
payload: "payload 1",
|
296
295
|
key: "key 1",
|
@@ -328,7 +327,7 @@ describe Rdkafka::Consumer do
|
|
328
327
|
before :all do
|
329
328
|
# Make sure there are some messages.
|
330
329
|
handles = []
|
331
|
-
producer =
|
330
|
+
producer = rdkafka_producer_config.producer
|
332
331
|
10.times do
|
333
332
|
(0..2).each do |i|
|
334
333
|
handles << producer.produce(
|
@@ -404,7 +403,7 @@ describe Rdkafka::Consumer do
|
|
404
403
|
config = {}
|
405
404
|
config[:'enable.auto.offset.store'] = false
|
406
405
|
config[:'enable.auto.commit'] = false
|
407
|
-
@new_consumer =
|
406
|
+
@new_consumer = rdkafka_consumer_config(config).consumer
|
408
407
|
@new_consumer.subscribe("consume_test_topic")
|
409
408
|
wait_for_assignment(@new_consumer)
|
410
409
|
end
|
@@ -459,13 +458,13 @@ describe Rdkafka::Consumer do
|
|
459
458
|
end
|
460
459
|
|
461
460
|
describe "#lag" do
|
462
|
-
let(:
|
461
|
+
let(:consumer) { rdkafka_consumer_config(:"enable.partition.eof" => true).consumer }
|
463
462
|
|
464
463
|
it "should calculate the consumer lag" do
|
465
464
|
# Make sure there's a message in every partition and
|
466
465
|
# wait for the message to make sure everything is committed.
|
467
466
|
(0..2).each do |i|
|
468
|
-
|
467
|
+
producer.produce(
|
469
468
|
topic: "consume_test_topic",
|
470
469
|
key: "key lag #{i}",
|
471
470
|
partition: i
|
@@ -508,7 +507,7 @@ describe Rdkafka::Consumer do
|
|
508
507
|
|
509
508
|
# Produce message on every topic again
|
510
509
|
(0..2).each do |i|
|
511
|
-
|
510
|
+
producer.produce(
|
512
511
|
topic: "consume_test_topic",
|
513
512
|
key: "key lag #{i}",
|
514
513
|
partition: i
|
@@ -824,11 +823,14 @@ describe Rdkafka::Consumer do
|
|
824
823
|
|
825
824
|
context "error raised from poll and yield_on_error is true" do
|
826
825
|
it "should yield buffered exceptions on rebalance, then break" do
|
827
|
-
config =
|
828
|
-
|
826
|
+
config = rdkafka_consumer_config(
|
827
|
+
{
|
828
|
+
:"enable.auto.commit" => false,
|
829
|
+
:"enable.auto.offset.store" => false
|
830
|
+
}
|
831
|
+
)
|
829
832
|
consumer = config.consumer
|
830
833
|
consumer.subscribe(topic_name)
|
831
|
-
loop_count = 0
|
832
834
|
batches_yielded = []
|
833
835
|
exceptions_yielded = []
|
834
836
|
each_batch_iterations = 0
|
@@ -864,11 +866,14 @@ describe Rdkafka::Consumer do
|
|
864
866
|
|
865
867
|
context "error raised from poll and yield_on_error is false" do
|
866
868
|
it "should yield buffered exceptions on rebalance, then break" do
|
867
|
-
config =
|
868
|
-
|
869
|
+
config = rdkafka_consumer_config(
|
870
|
+
{
|
871
|
+
:"enable.auto.commit" => false,
|
872
|
+
:"enable.auto.offset.store" => false
|
873
|
+
}
|
874
|
+
)
|
869
875
|
consumer = config.consumer
|
870
876
|
consumer.subscribe(topic_name)
|
871
|
-
loop_count = 0
|
872
877
|
batches_yielded = []
|
873
878
|
exceptions_yielded = []
|
874
879
|
each_batch_iterations = 0
|
@@ -902,51 +907,64 @@ describe Rdkafka::Consumer do
|
|
902
907
|
end
|
903
908
|
|
904
909
|
describe "a rebalance listener" do
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
+
let(:consumer) do
|
911
|
+
config = rdkafka_consumer_config
|
912
|
+
config.consumer_rebalance_listener = listener
|
913
|
+
config.consumer
|
914
|
+
end
|
910
915
|
|
911
|
-
|
912
|
-
|
913
|
-
|
916
|
+
context "with a working listener" do
|
917
|
+
let(:listener) do
|
918
|
+
Struct.new(:queue) do
|
919
|
+
def on_partitions_assigned(consumer, list)
|
920
|
+
collect(:assign, list)
|
921
|
+
end
|
914
922
|
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
end
|
919
|
-
end.new([])
|
923
|
+
def on_partitions_revoked(consumer, list)
|
924
|
+
collect(:revoke, list)
|
925
|
+
end
|
920
926
|
|
921
|
-
|
927
|
+
def collect(name, list)
|
928
|
+
partitions = list.to_h.map { |key, values| [key, values.map(&:partition)] }.flatten
|
929
|
+
queue << ([name] + partitions)
|
930
|
+
end
|
931
|
+
end.new([])
|
932
|
+
end
|
922
933
|
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
934
|
+
it "should get notifications" do
|
935
|
+
notify_listener(listener)
|
936
|
+
|
937
|
+
expect(listener.queue).to eq([
|
938
|
+
[:assign, "consume_test_topic", 0, 1, 2],
|
939
|
+
[:revoke, "consume_test_topic", 0, 1, 2]
|
940
|
+
])
|
941
|
+
end
|
927
942
|
end
|
928
943
|
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
944
|
+
context "with a broken listener" do
|
945
|
+
let(:listener) do
|
946
|
+
Struct.new(:queue) do
|
947
|
+
def on_partitions_assigned(consumer, list)
|
948
|
+
queue << :assigned
|
949
|
+
raise 'boom'
|
950
|
+
end
|
935
951
|
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
952
|
+
def on_partitions_revoked(consumer, list)
|
953
|
+
queue << :revoked
|
954
|
+
raise 'boom'
|
955
|
+
end
|
956
|
+
end.new([])
|
957
|
+
end
|
941
958
|
|
942
|
-
|
959
|
+
it 'should handle callback exceptions' do
|
960
|
+
notify_listener(listener)
|
943
961
|
|
944
|
-
|
962
|
+
expect(listener.queue).to eq([:assigned, :revoked])
|
963
|
+
end
|
945
964
|
end
|
946
965
|
|
947
966
|
def notify_listener(listener)
|
948
967
|
# 1. subscribe and poll
|
949
|
-
config.consumer_rebalance_listener = listener
|
950
968
|
consumer.subscribe("consume_test_topic")
|
951
969
|
wait_for_assignment(consumer)
|
952
970
|
consumer.poll(100)
|
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
require "securerandom"
|
3
3
|
|
4
4
|
describe Rdkafka::Metadata do
|
5
|
-
let(:config) {
|
5
|
+
let(:config) { rdkafka_consumer_config }
|
6
6
|
let(:native_config) { config.send(:native_config) }
|
7
7
|
let(:native_kafka) { config.send(:native_kafka, native_config, :rd_kafka_consumer) }
|
8
8
|
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rdkafka::Producer::Client do
|
4
|
+
let(:config) { rdkafka_producer_config }
|
5
|
+
let(:native) { config.send(:native_kafka, config.send(:native_config), :rd_kafka_producer) }
|
6
|
+
let(:closing) { false }
|
7
|
+
let(:thread) { double(Thread) }
|
8
|
+
|
9
|
+
subject(:client) { described_class.new(native) }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(Rdkafka::Bindings).to receive(:rd_kafka_poll).with(instance_of(FFI::Pointer), 250).and_call_original
|
13
|
+
allow(Rdkafka::Bindings).to receive(:rd_kafka_outq_len).with(instance_of(FFI::Pointer)).and_return(0).and_call_original
|
14
|
+
allow(Rdkafka::Bindings).to receive(:rd_kafka_destroy)
|
15
|
+
allow(Thread).to receive(:new).and_return(thread)
|
16
|
+
|
17
|
+
allow(thread).to receive(:[]=).with(:closing, anything)
|
18
|
+
allow(thread).to receive(:join)
|
19
|
+
allow(thread).to receive(:abort_on_exception=).with(anything)
|
20
|
+
end
|
21
|
+
|
22
|
+
context "defaults" do
|
23
|
+
it "sets the thread to abort on exception" do
|
24
|
+
expect(thread).to receive(:abort_on_exception=).with(true)
|
25
|
+
|
26
|
+
client
|
27
|
+
end
|
28
|
+
|
29
|
+
it "sets the thread `closing` flag to false" do
|
30
|
+
expect(thread).to receive(:[]=).with(:closing, false)
|
31
|
+
|
32
|
+
client
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "the polling thread" do
|
37
|
+
it "is created" do
|
38
|
+
expect(Thread).to receive(:new)
|
39
|
+
|
40
|
+
client
|
41
|
+
end
|
42
|
+
|
43
|
+
it "polls the native with default 250ms timeout" do
|
44
|
+
polling_loop_expects do
|
45
|
+
expect(Rdkafka::Bindings).to receive(:rd_kafka_poll).with(instance_of(FFI::Pointer), 250).at_least(:once)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "check the out queue of native client" do
|
50
|
+
polling_loop_expects do
|
51
|
+
expect(Rdkafka::Bindings).to receive(:rd_kafka_outq_len).with(native).at_least(:once)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def polling_loop_expects(&block)
|
57
|
+
Thread.current[:closing] = true # this forces the loop break with line #12
|
58
|
+
|
59
|
+
allow(Thread).to receive(:new).and_yield do |_|
|
60
|
+
block.call
|
61
|
+
end.and_return(thread)
|
62
|
+
|
63
|
+
client
|
64
|
+
end
|
65
|
+
|
66
|
+
it "exposes `native` client" do
|
67
|
+
expect(client.native).to eq(native)
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when client was not yet closed (`nil`)" do
|
71
|
+
it "is not closed" do
|
72
|
+
expect(client.closed?).to eq(false)
|
73
|
+
end
|
74
|
+
|
75
|
+
context "and attempt to close" do
|
76
|
+
it "calls the `destroy` binding" do
|
77
|
+
expect(Rdkafka::Bindings).to receive(:rd_kafka_destroy).with(native)
|
78
|
+
|
79
|
+
client.close
|
80
|
+
end
|
81
|
+
|
82
|
+
it "indicates to the polling thread that it is closing" do
|
83
|
+
expect(thread).to receive(:[]=).with(:closing, true)
|
84
|
+
|
85
|
+
client.close
|
86
|
+
end
|
87
|
+
|
88
|
+
it "joins the polling thread" do
|
89
|
+
expect(thread).to receive(:join)
|
90
|
+
|
91
|
+
client.close
|
92
|
+
end
|
93
|
+
|
94
|
+
it "closes and unassign the native client" do
|
95
|
+
client.close
|
96
|
+
|
97
|
+
expect(client.native).to eq(nil)
|
98
|
+
expect(client.closed?).to eq(true)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when client was already closed" do
|
104
|
+
before { client.close }
|
105
|
+
|
106
|
+
it "is closed" do
|
107
|
+
expect(client.closed?).to eq(true)
|
108
|
+
end
|
109
|
+
|
110
|
+
context "and attempt to close again" do
|
111
|
+
it "does not call the `destroy` binding" do
|
112
|
+
expect(Rdkafka::Bindings).not_to receive(:rd_kafka_destroy)
|
113
|
+
|
114
|
+
client.close
|
115
|
+
end
|
116
|
+
|
117
|
+
it "does not indicate to the polling thread that it is closing" do
|
118
|
+
expect(thread).not_to receive(:[]=).with(:closing, true)
|
119
|
+
|
120
|
+
client.close
|
121
|
+
end
|
122
|
+
|
123
|
+
it "does not join the polling thread" do
|
124
|
+
expect(thread).not_to receive(:join)
|
125
|
+
|
126
|
+
client.close
|
127
|
+
end
|
128
|
+
|
129
|
+
it "does not close and unassign the native client again" do
|
130
|
+
client.close
|
131
|
+
|
132
|
+
expect(client.native).to eq(nil)
|
133
|
+
expect(client.closed?).to eq(true)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it "provide a finalizer Proc that closes the `native` client" do
|
139
|
+
expect(client.closed?).to eq(false)
|
140
|
+
|
141
|
+
client.finalizer.call("some-ignored-object-id")
|
142
|
+
|
143
|
+
expect(client.closed?).to eq(true)
|
144
|
+
end
|
145
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
|
+
require "zlib"
|
2
3
|
|
3
4
|
describe Rdkafka::Producer do
|
4
|
-
let(:producer) {
|
5
|
-
let(:consumer) {
|
5
|
+
let(:producer) { rdkafka_producer_config.producer }
|
6
|
+
let(:consumer) { rdkafka_consumer_config.consumer }
|
6
7
|
|
7
8
|
after do
|
8
9
|
# Registry should always end up being empty
|
@@ -48,6 +49,27 @@ describe Rdkafka::Producer do
|
|
48
49
|
# Callback should have been called
|
49
50
|
expect(@callback_called).to be true
|
50
51
|
end
|
52
|
+
|
53
|
+
it "should provide handle" do
|
54
|
+
@callback_handle = nil
|
55
|
+
|
56
|
+
producer.delivery_callback = lambda { |_, handle| @callback_handle = handle }
|
57
|
+
|
58
|
+
# Produce a message
|
59
|
+
handle = producer.produce(
|
60
|
+
topic: "produce_test_topic",
|
61
|
+
payload: "payload",
|
62
|
+
key: "key"
|
63
|
+
)
|
64
|
+
|
65
|
+
# Wait for it to be delivered
|
66
|
+
handle.wait(max_wait_timeout: 15)
|
67
|
+
|
68
|
+
# Join the producer thread.
|
69
|
+
producer.close
|
70
|
+
|
71
|
+
expect(handle).to be @callback_handle
|
72
|
+
end
|
51
73
|
end
|
52
74
|
|
53
75
|
context "with a callable object" do
|
@@ -92,6 +114,36 @@ describe Rdkafka::Producer do
|
|
92
114
|
expect(called_report.first.partition).to eq 1
|
93
115
|
expect(called_report.first.offset).to be >= 0
|
94
116
|
end
|
117
|
+
|
118
|
+
it "should provide handle" do
|
119
|
+
callback_handles = []
|
120
|
+
callback = Class.new do
|
121
|
+
def initialize(callback_handles)
|
122
|
+
@callback_handles = callback_handles
|
123
|
+
end
|
124
|
+
|
125
|
+
def call(_, handle)
|
126
|
+
@callback_handles << handle
|
127
|
+
end
|
128
|
+
end
|
129
|
+
producer.delivery_callback = callback.new(callback_handles)
|
130
|
+
|
131
|
+
# Produce a message
|
132
|
+
handle = producer.produce(
|
133
|
+
topic: "produce_test_topic",
|
134
|
+
payload: "payload",
|
135
|
+
key: "key"
|
136
|
+
)
|
137
|
+
|
138
|
+
# Wait for it to be delivered
|
139
|
+
handle.wait(max_wait_timeout: 15)
|
140
|
+
|
141
|
+
# Join the producer thread.
|
142
|
+
producer.close
|
143
|
+
|
144
|
+
# Callback should have been called
|
145
|
+
expect(handle).to be callback_handles.first
|
146
|
+
end
|
95
147
|
end
|
96
148
|
|
97
149
|
it "should not accept a callback that's not callable" do
|
@@ -375,20 +427,16 @@ describe Rdkafka::Producer do
|
|
375
427
|
end
|
376
428
|
end
|
377
429
|
|
378
|
-
it "should produce a message in a forked process" do
|
430
|
+
it "should produce a message in a forked process", skip: defined?(JRUBY_VERSION) && "Kernel#fork is not available" do
|
379
431
|
# Fork, produce a message, send the report over a pipe and
|
380
432
|
# wait for and check the message in the main process.
|
381
|
-
|
382
|
-
# Kernel#fork is not available in JRuby
|
383
|
-
skip if defined?(JRUBY_VERSION)
|
384
|
-
|
385
433
|
reader, writer = IO.pipe
|
386
434
|
|
387
435
|
fork do
|
388
436
|
reader.close
|
389
437
|
|
390
438
|
# Avoids sharing the socket between processes.
|
391
|
-
producer =
|
439
|
+
producer = rdkafka_producer_config.producer
|
392
440
|
|
393
441
|
handle = producer.produce(
|
394
442
|
topic: "produce_test_topic",
|
data/spec/spec_helper.rb
CHANGED
@@ -8,27 +8,57 @@ end
|
|
8
8
|
require "pry"
|
9
9
|
require "rspec"
|
10
10
|
require "rdkafka"
|
11
|
+
require "timeout"
|
11
12
|
|
12
|
-
def
|
13
|
-
|
13
|
+
def rdkafka_base_config
|
14
|
+
{
|
14
15
|
:"api.version.request" => false,
|
15
16
|
:"broker.version.fallback" => "1.0",
|
16
17
|
:"bootstrap.servers" => "localhost:9092",
|
17
|
-
:"group.id" => "ruby-test-#{Random.new.rand(0..1_000_000)}",
|
18
|
-
:"auto.offset.reset" => "earliest",
|
19
|
-
:"enable.partition.eof" => false
|
20
18
|
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def rdkafka_config(config_overrides={})
|
22
|
+
# Generate the base config
|
23
|
+
config = rdkafka_base_config
|
24
|
+
# Merge overrides
|
25
|
+
config.merge!(config_overrides)
|
26
|
+
# Return it
|
27
|
+
Rdkafka::Config.new(config)
|
28
|
+
end
|
29
|
+
|
30
|
+
def rdkafka_consumer_config(config_overrides={})
|
31
|
+
# Generate the base config
|
32
|
+
config = rdkafka_base_config
|
33
|
+
# Add consumer specific fields to it
|
34
|
+
config[:"auto.offset.reset"] = "earliest"
|
35
|
+
config[:"enable.partition.eof"] = false
|
36
|
+
config[:"group.id"] = "ruby-test-#{Random.new.rand(0..1_000_000)}"
|
37
|
+
# Enable debug mode if required
|
38
|
+
if ENV["DEBUG_CONSUMER"]
|
39
|
+
config[:debug] = "cgrp,topic,fetch"
|
40
|
+
end
|
41
|
+
# Merge overrides
|
42
|
+
config.merge!(config_overrides)
|
43
|
+
# Return it
|
44
|
+
Rdkafka::Config.new(config)
|
45
|
+
end
|
46
|
+
|
47
|
+
def rdkafka_producer_config(config_overrides={})
|
48
|
+
# Generate the base config
|
49
|
+
config = rdkafka_base_config
|
50
|
+
# Enable debug mode if required
|
21
51
|
if ENV["DEBUG_PRODUCER"]
|
22
52
|
config[:debug] = "broker,topic,msg"
|
23
|
-
elsif ENV["DEBUG_CONSUMER"]
|
24
|
-
config[:debug] = "cgrp,topic,fetch"
|
25
53
|
end
|
54
|
+
# Merge overrides
|
26
55
|
config.merge!(config_overrides)
|
56
|
+
# Return it
|
27
57
|
Rdkafka::Config.new(config)
|
28
58
|
end
|
29
59
|
|
30
60
|
def new_native_client
|
31
|
-
config =
|
61
|
+
config = rdkafka_consumer_config
|
32
62
|
config.send(:native_kafka, config.send(:native_config), :rd_kafka_producer)
|
33
63
|
end
|
34
64
|
|
@@ -42,7 +72,7 @@ end
|
|
42
72
|
|
43
73
|
def wait_for_message(topic:, delivery_report:, timeout_in_seconds: 30, consumer: nil)
|
44
74
|
new_consumer = !!consumer
|
45
|
-
consumer ||=
|
75
|
+
consumer ||= rdkafka_consumer_config.consumer
|
46
76
|
consumer.subscribe(topic)
|
47
77
|
timeout = Time.now.to_i + timeout_in_seconds
|
48
78
|
loop do
|
@@ -75,6 +105,9 @@ def wait_for_unassignment(consumer)
|
|
75
105
|
end
|
76
106
|
|
77
107
|
RSpec.configure do |config|
|
108
|
+
config.filter_run focus: true
|
109
|
+
config.run_all_when_everything_filtered = true
|
110
|
+
|
78
111
|
config.before(:suite) do
|
79
112
|
admin = rdkafka_config.admin
|
80
113
|
{
|
@@ -95,4 +128,12 @@ RSpec.configure do |config|
|
|
95
128
|
end
|
96
129
|
admin.close
|
97
130
|
end
|
131
|
+
|
132
|
+
config.around(:each) do |example|
|
133
|
+
# Timeout specs after a minute. If they take longer
|
134
|
+
# they are probably stuck
|
135
|
+
Timeout::timeout(60) do
|
136
|
+
example.run
|
137
|
+
end
|
138
|
+
end
|
98
139
|
end
|