karafka-rdkafka 0.13.2 → 0.13.9
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
- 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
|