karafka-rdkafka 0.13.2 → 0.13.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +9 -4
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +54 -26
- data/{LICENSE → MIT-LICENSE} +2 -1
- data/README.md +19 -20
- data/certs/cert_chain.pem +21 -21
- data/docker-compose.yml +16 -15
- data/ext/README.md +1 -1
- data/ext/Rakefile +1 -1
- data/karafka-rdkafka.gemspec +2 -2
- data/lib/rdkafka/abstract_handle.rb +41 -27
- data/lib/rdkafka/admin/create_partitions_handle.rb +6 -3
- data/lib/rdkafka/admin/create_topic_handle.rb +6 -3
- data/lib/rdkafka/admin/delete_topic_handle.rb +6 -3
- data/lib/rdkafka/admin.rb +6 -7
- data/lib/rdkafka/bindings.rb +24 -6
- data/lib/rdkafka/config.rb +53 -19
- data/lib/rdkafka/consumer/headers.rb +2 -4
- data/lib/rdkafka/consumer.rb +119 -93
- data/lib/rdkafka/error.rb +60 -1
- data/lib/rdkafka/helpers/time.rb +14 -0
- data/lib/rdkafka/metadata.rb +4 -4
- data/lib/rdkafka/native_kafka.rb +6 -1
- data/lib/rdkafka/producer/delivery_handle.rb +16 -1
- data/lib/rdkafka/producer/delivery_report.rb +3 -2
- data/lib/rdkafka/producer.rb +89 -17
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +10 -1
- data/renovate.json +6 -0
- data/spec/rdkafka/abstract_handle_spec.rb +0 -2
- data/spec/rdkafka/admin/create_topic_handle_spec.rb +4 -4
- data/spec/rdkafka/admin/create_topic_report_spec.rb +0 -2
- data/spec/rdkafka/admin/delete_topic_handle_spec.rb +3 -3
- data/spec/rdkafka/admin/delete_topic_report_spec.rb +0 -2
- data/spec/rdkafka/admin_spec.rb +1 -2
- data/spec/rdkafka/bindings_spec.rb +0 -1
- data/spec/rdkafka/callbacks_spec.rb +0 -2
- data/spec/rdkafka/config_spec.rb +8 -2
- data/spec/rdkafka/consumer/headers_spec.rb +0 -2
- data/spec/rdkafka/consumer/message_spec.rb +0 -2
- data/spec/rdkafka/consumer/partition_spec.rb +0 -2
- data/spec/rdkafka/consumer/topic_partition_list_spec.rb +0 -2
- data/spec/rdkafka/consumer_spec.rb +122 -38
- data/spec/rdkafka/error_spec.rb +0 -2
- data/spec/rdkafka/metadata_spec.rb +2 -3
- data/spec/rdkafka/native_kafka_spec.rb +2 -3
- data/spec/rdkafka/producer/delivery_handle_spec.rb +15 -2
- data/spec/rdkafka/producer/delivery_report_spec.rb +0 -2
- data/spec/rdkafka/producer_spec.rb +293 -1
- data/spec/spec_helper.rb +7 -1
- data.tar.gz.sig +0 -0
- metadata +31 -28
- metadata.gz.sig +0 -0
- data/certs/karafka-pro.pem +0 -11
data/lib/rdkafka/producer.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "objspace"
|
4
|
-
|
5
3
|
module Rdkafka
|
6
4
|
# A producer for Kafka messages. To create a producer set up a {Config} and call {Config#producer producer} on that.
|
7
5
|
class Producer
|
6
|
+
include Helpers::Time
|
7
|
+
|
8
8
|
# Cache partitions count for 30 seconds
|
9
9
|
PARTITIONS_COUNT_TTL = 30
|
10
10
|
|
@@ -63,6 +63,47 @@ module Rdkafka
|
|
63
63
|
@delivery_callback_arity = arity(callback)
|
64
64
|
end
|
65
65
|
|
66
|
+
# Init transactions
|
67
|
+
# Run once per producer
|
68
|
+
def init_transactions
|
69
|
+
closed_producer_check(__method__)
|
70
|
+
|
71
|
+
@native_kafka.with_inner do |inner|
|
72
|
+
response_ptr = Rdkafka::Bindings.rd_kafka_init_transactions(inner, -1)
|
73
|
+
|
74
|
+
Rdkafka::RdkafkaError.validate!(response_ptr) || true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def begin_transaction
|
79
|
+
closed_producer_check(__method__)
|
80
|
+
|
81
|
+
@native_kafka.with_inner do |inner|
|
82
|
+
response_ptr = Rdkafka::Bindings.rd_kafka_begin_transaction(inner)
|
83
|
+
|
84
|
+
Rdkafka::RdkafkaError.validate!(response_ptr)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def commit_transaction(timeout_ms = -1)
|
89
|
+
closed_producer_check(__method__)
|
90
|
+
|
91
|
+
@native_kafka.with_inner do |inner|
|
92
|
+
response_ptr = Rdkafka::Bindings.rd_kafka_commit_transaction(inner, timeout_ms)
|
93
|
+
|
94
|
+
Rdkafka::RdkafkaError.validate!(response_ptr)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def abort_transaction(timeout_ms = -1)
|
99
|
+
closed_producer_check(__method__)
|
100
|
+
|
101
|
+
@native_kafka.with_inner do |inner|
|
102
|
+
response_ptr = Rdkafka::Bindings.rd_kafka_abort_transaction(inner, timeout_ms)
|
103
|
+
Rdkafka::RdkafkaError.validate!(response_ptr)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
66
107
|
# Close this producer and wait for the internal poll queue to empty.
|
67
108
|
def close
|
68
109
|
return if closed?
|
@@ -79,27 +120,63 @@ module Rdkafka
|
|
79
120
|
# in seconds. Call this before closing a producer to ensure delivery of all messages.
|
80
121
|
#
|
81
122
|
# @param timeout_ms [Integer] how long should we wait for flush of all messages
|
123
|
+
# @return [Boolean] true if no more data and all was flushed, false in case there are still
|
124
|
+
# outgoing messages after the timeout
|
125
|
+
#
|
126
|
+
# @note We raise an exception for other errors because based on the librdkafka docs, there
|
127
|
+
# should be no other errors.
|
128
|
+
#
|
129
|
+
# @note For `timed_out` we do not raise an error to keep it backwards compatible
|
82
130
|
def flush(timeout_ms=5_000)
|
83
131
|
closed_producer_check(__method__)
|
84
132
|
|
133
|
+
error = @native_kafka.with_inner do |inner|
|
134
|
+
response = Rdkafka::Bindings.rd_kafka_flush(inner, timeout_ms)
|
135
|
+
Rdkafka::RdkafkaError.build(response)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Early skip not to build the error message
|
139
|
+
return true unless error
|
140
|
+
return false if error.code == :timed_out
|
141
|
+
|
142
|
+
raise(error)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Purges the outgoing queue and releases all resources.
|
146
|
+
#
|
147
|
+
# Useful when closing the producer with outgoing messages to unstable clusters or when for
|
148
|
+
# any other reasons waiting cannot go on anymore. This purges both the queue and all the
|
149
|
+
# inflight requests + updates the delivery handles statuses so they can be materialized into
|
150
|
+
# `purge_queue` errors.
|
151
|
+
def purge
|
152
|
+
closed_producer_check(__method__)
|
153
|
+
|
85
154
|
@native_kafka.with_inner do |inner|
|
86
|
-
|
155
|
+
response = Bindings.rd_kafka_purge(
|
156
|
+
inner,
|
157
|
+
Bindings::RD_KAFKA_PURGE_F_QUEUE | Bindings::RD_KAFKA_PURGE_F_INFLIGHT
|
158
|
+
)
|
159
|
+
|
160
|
+
Rdkafka::RdkafkaError.validate!(response)
|
87
161
|
end
|
162
|
+
|
163
|
+
# Wait for the purge to affect everything
|
164
|
+
sleep(0.001) until flush(100)
|
165
|
+
|
166
|
+
true
|
88
167
|
end
|
89
168
|
|
90
169
|
# Partition count for a given topic.
|
91
|
-
# NOTE: If 'allow.auto.create.topics' is set to true in the broker, the topic will be auto-created after returning nil.
|
92
170
|
#
|
93
171
|
# @param topic [String] The topic name.
|
172
|
+
# @return [Integer] partition count for a given topic
|
94
173
|
#
|
95
|
-
# @
|
96
|
-
#
|
97
|
-
# We cache the partition count for a given topic for given time
|
98
|
-
# This prevents us in case someone uses `partition_key` from querying for the count with
|
99
|
-
# each message. Instead we query once every 30 seconds at most
|
174
|
+
# @note If 'allow.auto.create.topics' is set to true in the broker, the topic will be
|
175
|
+
# auto-created after returning nil.
|
100
176
|
#
|
101
|
-
# @
|
102
|
-
#
|
177
|
+
# @note We cache the partition count for a given topic for given time.
|
178
|
+
# This prevents us in case someone uses `partition_key` from querying for the count with
|
179
|
+
# each message. Instead we query once every 30 seconds at most
|
103
180
|
def partition_count(topic)
|
104
181
|
closed_producer_check(__method__)
|
105
182
|
|
@@ -208,7 +285,7 @@ module Rdkafka
|
|
208
285
|
# Raise error if the produce call was not successful
|
209
286
|
if response != 0
|
210
287
|
DeliveryHandle.remove(delivery_handle.to_ptr.address)
|
211
|
-
|
288
|
+
Rdkafka::RdkafkaError.validate!(response)
|
212
289
|
end
|
213
290
|
|
214
291
|
delivery_handle
|
@@ -229,11 +306,6 @@ module Rdkafka
|
|
229
306
|
|
230
307
|
private
|
231
308
|
|
232
|
-
def monotonic_now
|
233
|
-
# needed because Time.now can go backwards
|
234
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
235
|
-
end
|
236
|
-
|
237
309
|
def closed_producer_check(method)
|
238
310
|
raise Rdkafka::ClosedProducerError.new(method) if closed?
|
239
311
|
end
|
data/lib/rdkafka/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Rdkafka
|
4
|
-
VERSION = "0.13.
|
5
|
-
LIBRDKAFKA_VERSION = "2.
|
6
|
-
LIBRDKAFKA_SOURCE_SHA256 = "
|
4
|
+
VERSION = "0.13.9"
|
5
|
+
LIBRDKAFKA_VERSION = "2.2.0"
|
6
|
+
LIBRDKAFKA_SOURCE_SHA256 = "af9a820cbecbc64115629471df7c7cecd40403b6c34bfdbb9223152677a47226"
|
7
7
|
end
|
data/lib/rdkafka.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "logger"
|
4
|
+
require "objspace"
|
5
|
+
require "ffi"
|
6
|
+
require "json"
|
4
7
|
|
8
|
+
require "rdkafka/version"
|
9
|
+
require "rdkafka/helpers/time"
|
5
10
|
require "rdkafka/abstract_handle"
|
6
11
|
require "rdkafka/admin"
|
7
12
|
require "rdkafka/admin/create_topic_handle"
|
@@ -24,3 +29,7 @@ require "rdkafka/native_kafka"
|
|
24
29
|
require "rdkafka/producer"
|
25
30
|
require "rdkafka/producer/delivery_handle"
|
26
31
|
require "rdkafka/producer/delivery_report"
|
32
|
+
|
33
|
+
# Main Rdkafka namespace of this gem
|
34
|
+
module Rdkafka
|
35
|
+
end
|
data/renovate.json
ADDED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
3
|
describe Rdkafka::Admin::CreateTopicHandle do
|
6
4
|
let(:response) { 0 }
|
7
5
|
|
@@ -45,10 +43,12 @@ describe Rdkafka::Admin::CreateTopicHandle do
|
|
45
43
|
describe "#raise_error" do
|
46
44
|
let(:pending_handle) { false }
|
47
45
|
|
48
|
-
|
46
|
+
before { subject[:response] = -1 }
|
47
|
+
|
48
|
+
it "should raise the appropriate error when there is an error" do
|
49
49
|
expect {
|
50
50
|
subject.raise_error
|
51
|
-
}.to raise_exception(Rdkafka::RdkafkaError, /
|
51
|
+
}.to raise_exception(Rdkafka::RdkafkaError, /Unknown broker error \(unknown\)/)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
3
|
describe Rdkafka::Admin::DeleteTopicHandle do
|
6
4
|
let(:response) { 0 }
|
7
5
|
|
@@ -45,10 +43,12 @@ describe Rdkafka::Admin::DeleteTopicHandle do
|
|
45
43
|
describe "#raise_error" do
|
46
44
|
let(:pending_handle) { false }
|
47
45
|
|
46
|
+
before { subject[:response] = -1 }
|
47
|
+
|
48
48
|
it "should raise the appropriate error" do
|
49
49
|
expect {
|
50
50
|
subject.raise_error
|
51
|
-
}.to raise_exception(Rdkafka::RdkafkaError, /
|
51
|
+
}.to raise_exception(Rdkafka::RdkafkaError, /Unknown broker error \(unknown\)/)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
data/spec/rdkafka/admin_spec.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
3
|
require "ostruct"
|
5
4
|
|
6
5
|
describe Rdkafka::Admin do
|
@@ -33,7 +32,7 @@ describe Rdkafka::Admin do
|
|
33
32
|
}.to raise_exception { |ex|
|
34
33
|
expect(ex).to be_a(Rdkafka::RdkafkaError)
|
35
34
|
expect(ex.message).to match(/Broker: Invalid topic \(topic_exception\)/)
|
36
|
-
expect(ex.broker_message).to match(/Topic name.*is
|
35
|
+
expect(ex.broker_message).to match(/Topic name.*is invalid: .* contains one or more characters other than ASCII alphanumerics, '.', '_' and '-'/)
|
37
36
|
}
|
38
37
|
end
|
39
38
|
end
|
data/spec/rdkafka/config_spec.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
3
|
describe Rdkafka::Config do
|
6
4
|
context "logger" do
|
7
5
|
it "should have a default logger" do
|
@@ -115,6 +113,14 @@ describe Rdkafka::Config do
|
|
115
113
|
consumer.close
|
116
114
|
end
|
117
115
|
|
116
|
+
it "should create a consumer with consumer_poll_set set to false" do
|
117
|
+
config = rdkafka_consumer_config
|
118
|
+
config.consumer_poll_set = false
|
119
|
+
consumer = config.consumer
|
120
|
+
expect(consumer).to be_a Rdkafka::Consumer
|
121
|
+
consumer.close
|
122
|
+
end
|
123
|
+
|
118
124
|
it "should raise an error when creating a consumer with invalid config" do
|
119
125
|
config = Rdkafka::Config.new('invalid.key' => 'value')
|
120
126
|
expect {
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
3
|
require "ostruct"
|
5
4
|
require 'securerandom'
|
6
5
|
|
@@ -55,6 +54,30 @@ describe Rdkafka::Consumer do
|
|
55
54
|
consumer.subscription
|
56
55
|
}.to raise_error(Rdkafka::RdkafkaError)
|
57
56
|
end
|
57
|
+
|
58
|
+
context "when using consumer without the poll set" do
|
59
|
+
let(:consumer) do
|
60
|
+
config = rdkafka_consumer_config
|
61
|
+
config.consumer_poll_set = false
|
62
|
+
config.consumer
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should subscribe, unsubscribe and return the subscription" do
|
66
|
+
expect(consumer.subscription).to be_empty
|
67
|
+
|
68
|
+
consumer.subscribe("consume_test_topic")
|
69
|
+
|
70
|
+
expect(consumer.subscription).not_to be_empty
|
71
|
+
expected_subscription = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
72
|
+
list.add_topic("consume_test_topic")
|
73
|
+
end
|
74
|
+
expect(consumer.subscription).to eq expected_subscription
|
75
|
+
|
76
|
+
consumer.unsubscribe
|
77
|
+
|
78
|
+
expect(consumer.subscription).to be_empty
|
79
|
+
end
|
80
|
+
end
|
58
81
|
end
|
59
82
|
|
60
83
|
describe "#pause and #resume" do
|
@@ -337,8 +360,9 @@ describe Rdkafka::Consumer do
|
|
337
360
|
end
|
338
361
|
end
|
339
362
|
|
340
|
-
|
341
|
-
|
363
|
+
|
364
|
+
describe "#position, #commit, #committed and #store_offset" do
|
365
|
+
# Make sure there are messages to work with
|
342
366
|
let!(:report) do
|
343
367
|
producer.produce(
|
344
368
|
topic: "consume_test_topic",
|
@@ -356,29 +380,33 @@ describe Rdkafka::Consumer do
|
|
356
380
|
)
|
357
381
|
end
|
358
382
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
383
|
+
describe "#position" do
|
384
|
+
it "should only accept a topic partition list in position if not nil" do
|
385
|
+
expect {
|
386
|
+
consumer.position("list")
|
387
|
+
}.to raise_error TypeError
|
388
|
+
end
|
363
389
|
end
|
364
390
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
391
|
+
describe "#committed" do
|
392
|
+
it "should only accept a topic partition list in commit if not nil" do
|
393
|
+
expect {
|
394
|
+
consumer.commit("list")
|
395
|
+
}.to raise_error TypeError
|
396
|
+
end
|
370
397
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
398
|
+
it "should commit in sync mode" do
|
399
|
+
expect {
|
400
|
+
consumer.commit(nil, true)
|
401
|
+
}.not_to raise_error
|
402
|
+
end
|
375
403
|
end
|
376
404
|
|
377
405
|
context "with a committed consumer" do
|
378
406
|
before :all do
|
379
407
|
# Make sure there are some messages.
|
380
408
|
handles = []
|
381
|
-
producer =
|
409
|
+
producer = rdkafka_config.producer
|
382
410
|
10.times do
|
383
411
|
(0..2).each do |i|
|
384
412
|
handles << producer.produce(
|
@@ -422,31 +450,33 @@ describe Rdkafka::Consumer do
|
|
422
450
|
}.to raise_error(Rdkafka::RdkafkaError)
|
423
451
|
end
|
424
452
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
453
|
+
describe "#committed" do
|
454
|
+
it "should fetch the committed offsets for the current assignment" do
|
455
|
+
partitions = consumer.committed.to_h["consume_test_topic"]
|
456
|
+
expect(partitions).not_to be_nil
|
457
|
+
expect(partitions[0].offset).to eq 1
|
458
|
+
end
|
430
459
|
|
431
|
-
|
432
|
-
|
433
|
-
|
460
|
+
it "should fetch the committed offsets for a specified topic partition list" do
|
461
|
+
list = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
462
|
+
list.add_topic("consume_test_topic", [0, 1, 2])
|
463
|
+
end
|
464
|
+
partitions = consumer.committed(list).to_h["consume_test_topic"]
|
465
|
+
expect(partitions).not_to be_nil
|
466
|
+
expect(partitions[0].offset).to eq 1
|
467
|
+
expect(partitions[1].offset).to eq 1
|
468
|
+
expect(partitions[2].offset).to eq 1
|
434
469
|
end
|
435
|
-
partitions = consumer.committed(list).to_h["consume_test_topic"]
|
436
|
-
expect(partitions).not_to be_nil
|
437
|
-
expect(partitions[0].offset).to eq 1
|
438
|
-
expect(partitions[1].offset).to eq 1
|
439
|
-
expect(partitions[2].offset).to eq 1
|
440
|
-
end
|
441
470
|
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
471
|
+
it "should raise an error when getting committed fails" do
|
472
|
+
expect(Rdkafka::Bindings).to receive(:rd_kafka_committed).and_return(20)
|
473
|
+
list = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
474
|
+
list.add_topic("consume_test_topic", [0, 1, 2])
|
475
|
+
end
|
476
|
+
expect {
|
477
|
+
consumer.committed(list)
|
478
|
+
}.to raise_error Rdkafka::RdkafkaError
|
446
479
|
end
|
447
|
-
expect {
|
448
|
-
consumer.committed(list)
|
449
|
-
}.to raise_error Rdkafka::RdkafkaError
|
450
480
|
end
|
451
481
|
|
452
482
|
describe "#store_offset" do
|
@@ -467,6 +497,8 @@ describe Rdkafka::Consumer do
|
|
467
497
|
@new_consumer.store_offset(message)
|
468
498
|
@new_consumer.commit
|
469
499
|
|
500
|
+
# TODO use position here, should be at offset
|
501
|
+
|
470
502
|
list = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
471
503
|
list.add_topic("consume_test_topic", [0, 1, 2])
|
472
504
|
end
|
@@ -481,6 +513,35 @@ describe Rdkafka::Consumer do
|
|
481
513
|
@new_consumer.store_offset(message)
|
482
514
|
}.to raise_error Rdkafka::RdkafkaError
|
483
515
|
end
|
516
|
+
|
517
|
+
describe "#position" do
|
518
|
+
it "should fetch the positions for the current assignment" do
|
519
|
+
consumer.store_offset(message)
|
520
|
+
|
521
|
+
partitions = consumer.position.to_h["consume_test_topic"]
|
522
|
+
expect(partitions).not_to be_nil
|
523
|
+
expect(partitions[0].offset).to eq message.offset + 1
|
524
|
+
end
|
525
|
+
|
526
|
+
it "should fetch the positions for a specified assignment" do
|
527
|
+
consumer.store_offset(message)
|
528
|
+
|
529
|
+
list = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
530
|
+
list.add_topic_and_partitions_with_offsets("consume_test_topic", 0 => nil, 1 => nil, 2 => nil)
|
531
|
+
end
|
532
|
+
partitions = consumer.position(list).to_h["consume_test_topic"]
|
533
|
+
expect(partitions).not_to be_nil
|
534
|
+
expect(partitions[0].offset).to eq message.offset + 1
|
535
|
+
end
|
536
|
+
|
537
|
+
it "should raise an error when getting the position fails" do
|
538
|
+
expect(Rdkafka::Bindings).to receive(:rd_kafka_position).and_return(20)
|
539
|
+
|
540
|
+
expect {
|
541
|
+
consumer.position
|
542
|
+
}.to raise_error(Rdkafka::RdkafkaError)
|
543
|
+
end
|
544
|
+
end
|
484
545
|
end
|
485
546
|
end
|
486
547
|
end
|
@@ -1039,6 +1100,29 @@ describe Rdkafka::Consumer do
|
|
1039
1100
|
end
|
1040
1101
|
end
|
1041
1102
|
|
1103
|
+
# Only relevant in case of a consumer with separate queues
|
1104
|
+
describe '#events_poll' do
|
1105
|
+
let(:stats) { [] }
|
1106
|
+
|
1107
|
+
before { Rdkafka::Config.statistics_callback = ->(published) { stats << published } }
|
1108
|
+
|
1109
|
+
after { Rdkafka::Config.statistics_callback = nil }
|
1110
|
+
|
1111
|
+
let(:consumer) do
|
1112
|
+
config = rdkafka_consumer_config('statistics.interval.ms': 100)
|
1113
|
+
config.consumer_poll_set = false
|
1114
|
+
config.consumer
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
it "expect to run events_poll, operate and propagate stats on events_poll and not poll" do
|
1118
|
+
consumer.subscribe("consume_test_topic")
|
1119
|
+
consumer.poll(1_000)
|
1120
|
+
expect(stats).to be_empty
|
1121
|
+
consumer.events_poll(-1)
|
1122
|
+
expect(stats).not_to be_empty
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
|
1042
1126
|
describe "a rebalance listener" do
|
1043
1127
|
let(:consumer) do
|
1044
1128
|
config = rdkafka_consumer_config
|
data/spec/rdkafka/error_spec.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
3
|
require "securerandom"
|
5
4
|
|
6
5
|
describe Rdkafka::Metadata do
|
@@ -31,7 +30,7 @@ describe Rdkafka::Metadata do
|
|
31
30
|
it "#brokers returns our single broker" do
|
32
31
|
expect(subject.brokers.length).to eq(1)
|
33
32
|
expect(subject.brokers[0][:broker_id]).to eq(1)
|
34
|
-
expect(subject.brokers[0][:broker_name]).to eq("
|
33
|
+
expect(subject.brokers[0][:broker_name]).to eq("127.0.0.1")
|
35
34
|
expect(subject.brokers[0][:broker_port]).to eq(9092)
|
36
35
|
end
|
37
36
|
|
@@ -54,7 +53,7 @@ describe Rdkafka::Metadata do
|
|
54
53
|
it "#brokers returns our single broker" do
|
55
54
|
expect(subject.brokers.length).to eq(1)
|
56
55
|
expect(subject.brokers[0][:broker_id]).to eq(1)
|
57
|
-
expect(subject.brokers[0][:broker_name]).to eq("
|
56
|
+
expect(subject.brokers[0][:broker_name]).to eq("127.0.0.1")
|
58
57
|
expect(subject.brokers[0][:broker_port]).to eq(9092)
|
59
58
|
end
|
60
59
|
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
3
|
describe Rdkafka::NativeKafka do
|
6
4
|
let(:config) { rdkafka_producer_config }
|
7
5
|
let(:native) { config.send(:native_kafka, config.send(:native_config), :rd_kafka_producer) }
|
8
6
|
let(:closing) { false }
|
9
7
|
let(:thread) { double(Thread) }
|
8
|
+
let(:opaque) { Rdkafka::Opaque.new }
|
10
9
|
|
11
|
-
subject(:client) { described_class.new(native, run_polling_thread: true) }
|
10
|
+
subject(:client) { described_class.new(native, run_polling_thread: true, opaque: opaque) }
|
12
11
|
|
13
12
|
before do
|
14
13
|
allow(Thread).to receive(:new).and_return(thread)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
3
|
describe Rdkafka::Producer::DeliveryHandle do
|
6
4
|
let(:response) { 0 }
|
7
5
|
|
@@ -44,4 +42,19 @@ describe Rdkafka::Producer::DeliveryHandle do
|
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
45
|
+
|
46
|
+
describe '#create_result' do
|
47
|
+
let(:pending_handle) { false }
|
48
|
+
let(:report) { subject.create_result }
|
49
|
+
|
50
|
+
context 'when response is 0' do
|
51
|
+
it { expect(report.error).to eq(nil) }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when response is not 0' do
|
55
|
+
let(:response) { 1 }
|
56
|
+
|
57
|
+
it { expect(report.error).to eq(Rdkafka::RdkafkaError.new(response)) }
|
58
|
+
end
|
59
|
+
end
|
47
60
|
end
|