rdkafka 0.7.0 → 0.8.0.beta.1
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/.travis.yml +13 -1
- data/CHANGELOG.md +10 -2
- data/docker-compose.yml +15 -11
- data/ext/README.md +3 -15
- data/ext/Rakefile +23 -3
- data/lib/rdkafka.rb +1 -0
- data/lib/rdkafka/bindings.rb +20 -2
- data/lib/rdkafka/config.rb +2 -4
- data/lib/rdkafka/consumer.rb +94 -43
- data/lib/rdkafka/consumer/headers.rb +7 -5
- data/lib/rdkafka/consumer/topic_partition_list.rb +4 -14
- data/lib/rdkafka/error.rb +5 -0
- data/lib/rdkafka/metadata.rb +91 -0
- data/lib/rdkafka/producer.rb +25 -4
- data/lib/rdkafka/producer/delivery_report.rb +6 -1
- data/lib/rdkafka/version.rb +3 -3
- data/rdkafka.gemspec +1 -1
- data/spec/rdkafka/bindings_spec.rb +20 -2
- data/spec/rdkafka/config_spec.rb +6 -2
- data/spec/rdkafka/consumer/message_spec.rb +6 -1
- data/spec/rdkafka/consumer_spec.rb +24 -17
- data/spec/rdkafka/error_spec.rb +3 -3
- data/spec/rdkafka/producer/delivery_report_spec.rb +5 -1
- data/spec/rdkafka/producer_spec.rb +74 -15
- data/spec/spec_helper.rb +14 -3
- metadata +8 -8
data/spec/rdkafka/error_spec.rb
CHANGED
@@ -71,15 +71,15 @@ describe Rdkafka::RdkafkaError do
|
|
71
71
|
end
|
72
72
|
|
73
73
|
it "should not equal another error with a different error code" do
|
74
|
-
expect(subject).
|
74
|
+
expect(subject).not_to eq Rdkafka::RdkafkaError.new(20, "Error explanation")
|
75
75
|
end
|
76
76
|
|
77
77
|
it "should not equal another error with a different message" do
|
78
|
-
expect(subject).
|
78
|
+
expect(subject).not_to eq Rdkafka::RdkafkaError.new(10, "Different error explanation")
|
79
79
|
end
|
80
80
|
|
81
81
|
it "should not equal another error with no message" do
|
82
|
-
expect(subject).
|
82
|
+
expect(subject).not_to eq Rdkafka::RdkafkaError.new(10)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Rdkafka::Producer::DeliveryReport do
|
4
|
-
subject { Rdkafka::Producer::DeliveryReport.new(2, 100) }
|
4
|
+
subject { Rdkafka::Producer::DeliveryReport.new(2, 100, "error") }
|
5
5
|
|
6
6
|
it "should get the partition" do
|
7
7
|
expect(subject.partition).to eq 2
|
@@ -10,4 +10,8 @@ describe Rdkafka::Producer::DeliveryReport do
|
|
10
10
|
it "should get the offset" do
|
11
11
|
expect(subject.offset).to eq 100
|
12
12
|
end
|
13
|
+
|
14
|
+
it "should get the error" do
|
15
|
+
expect(subject.error).to eq "error"
|
16
|
+
end
|
13
17
|
end
|
@@ -2,10 +2,13 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Rdkafka::Producer do
|
4
4
|
let(:producer) { rdkafka_config.producer }
|
5
|
+
let(:consumer) { rdkafka_config.consumer }
|
5
6
|
|
6
7
|
after do
|
7
8
|
# Registry should always end up being empty
|
8
9
|
expect(Rdkafka::Producer::DeliveryHandle::REGISTRY).to be_empty
|
10
|
+
producer.close
|
11
|
+
consumer.close
|
9
12
|
end
|
10
13
|
|
11
14
|
context "delivery callback" do
|
@@ -27,6 +30,7 @@ describe Rdkafka::Producer do
|
|
27
30
|
it "should call the callback when a message is delivered" do
|
28
31
|
@callback_called = false
|
29
32
|
|
33
|
+
|
30
34
|
producer.delivery_callback = lambda do |report|
|
31
35
|
expect(report).not_to be_nil
|
32
36
|
expect(report.partition).to eq 1
|
@@ -42,7 +46,10 @@ describe Rdkafka::Producer do
|
|
42
46
|
)
|
43
47
|
|
44
48
|
# Wait for it to be delivered
|
45
|
-
handle.wait(max_wait_timeout:
|
49
|
+
handle.wait(max_wait_timeout: 15)
|
50
|
+
|
51
|
+
# Join the producer thread.
|
52
|
+
producer.close
|
46
53
|
|
47
54
|
# Callback should have been called
|
48
55
|
expect(@callback_called).to be true
|
@@ -55,7 +62,7 @@ describe Rdkafka::Producer do
|
|
55
62
|
payload: "payload",
|
56
63
|
key: "key"
|
57
64
|
)
|
58
|
-
}.to raise_error ArgumentError,
|
65
|
+
}.to raise_error ArgumentError, /missing keyword: [\:]?topic/
|
59
66
|
end
|
60
67
|
|
61
68
|
it "should produce a message" do
|
@@ -82,14 +89,15 @@ describe Rdkafka::Producer do
|
|
82
89
|
# Consume message and verify it's content
|
83
90
|
message = wait_for_message(
|
84
91
|
topic: "produce_test_topic",
|
85
|
-
delivery_report: report
|
92
|
+
delivery_report: report,
|
93
|
+
consumer: consumer
|
86
94
|
)
|
87
95
|
expect(message.partition).to eq 1
|
88
96
|
expect(message.payload).to eq "payload"
|
89
97
|
expect(message.key).to eq "key"
|
90
98
|
# Since api.version.request is on by default we will get
|
91
99
|
# the message creation timestamp if it's not set.
|
92
|
-
expect(message.timestamp).to be_within(
|
100
|
+
expect(message.timestamp).to be_within(10).of(Time.now)
|
93
101
|
end
|
94
102
|
|
95
103
|
it "should produce a message with a specified partition" do
|
@@ -105,12 +113,47 @@ describe Rdkafka::Producer do
|
|
105
113
|
# Consume message and verify it's content
|
106
114
|
message = wait_for_message(
|
107
115
|
topic: "produce_test_topic",
|
108
|
-
delivery_report: report
|
116
|
+
delivery_report: report,
|
117
|
+
consumer: consumer
|
109
118
|
)
|
110
119
|
expect(message.partition).to eq 1
|
111
120
|
expect(message.key).to eq "key partition"
|
112
121
|
end
|
113
122
|
|
123
|
+
it "should produce a message to the same partition with a similar partition key" do
|
124
|
+
# Avoid partitioner collisions.
|
125
|
+
while true
|
126
|
+
key = ('a'..'z').to_a.shuffle.take(10).join('')
|
127
|
+
partition_key = ('a'..'z').to_a.shuffle.take(10).join('')
|
128
|
+
partition_count = producer.partition_count('partitioner_test_topic')
|
129
|
+
break if (Zlib.crc32(key) % partition_count) != (Zlib.crc32(partition_key) % partition_count)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Produce a message with key, partition_key and key + partition_key
|
133
|
+
messages = [{key: key}, {partition_key: partition_key}, {key: key, partition_key: partition_key}]
|
134
|
+
|
135
|
+
messages = messages.map do |m|
|
136
|
+
handle = producer.produce(
|
137
|
+
topic: "partitioner_test_topic",
|
138
|
+
payload: "payload partition",
|
139
|
+
key: m[:key],
|
140
|
+
partition_key: m[:partition_key]
|
141
|
+
)
|
142
|
+
report = handle.wait(max_wait_timeout: 5)
|
143
|
+
|
144
|
+
wait_for_message(
|
145
|
+
topic: "partitioner_test_topic",
|
146
|
+
delivery_report: report,
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
expect(messages[0].partition).not_to eq(messages[2].partition)
|
151
|
+
expect(messages[1].partition).to eq(messages[2].partition)
|
152
|
+
expect(messages[0].key).to eq key
|
153
|
+
expect(messages[1].key).to be_nil
|
154
|
+
expect(messages[2].key).to eq key
|
155
|
+
end
|
156
|
+
|
114
157
|
it "should produce a message with utf-8 encoding" do
|
115
158
|
handle = producer.produce(
|
116
159
|
topic: "produce_test_topic",
|
@@ -122,7 +165,8 @@ describe Rdkafka::Producer do
|
|
122
165
|
# Consume message and verify it's content
|
123
166
|
message = wait_for_message(
|
124
167
|
topic: "produce_test_topic",
|
125
|
-
delivery_report: report
|
168
|
+
delivery_report: report,
|
169
|
+
consumer: consumer
|
126
170
|
)
|
127
171
|
|
128
172
|
expect(message.partition).to eq 1
|
@@ -154,7 +198,8 @@ describe Rdkafka::Producer do
|
|
154
198
|
# Consume message and verify it's content
|
155
199
|
message = wait_for_message(
|
156
200
|
topic: "produce_test_topic",
|
157
|
-
delivery_report: report
|
201
|
+
delivery_report: report,
|
202
|
+
consumer: consumer
|
158
203
|
)
|
159
204
|
|
160
205
|
expect(message.partition).to eq 2
|
@@ -174,7 +219,8 @@ describe Rdkafka::Producer do
|
|
174
219
|
# Consume message and verify it's content
|
175
220
|
message = wait_for_message(
|
176
221
|
topic: "produce_test_topic",
|
177
|
-
delivery_report: report
|
222
|
+
delivery_report: report,
|
223
|
+
consumer: consumer
|
178
224
|
)
|
179
225
|
|
180
226
|
expect(message.partition).to eq 2
|
@@ -193,7 +239,8 @@ describe Rdkafka::Producer do
|
|
193
239
|
# Consume message and verify it's content
|
194
240
|
message = wait_for_message(
|
195
241
|
topic: "produce_test_topic",
|
196
|
-
delivery_report: report
|
242
|
+
delivery_report: report,
|
243
|
+
consumer: consumer
|
197
244
|
)
|
198
245
|
|
199
246
|
expect(message.key).to be_nil
|
@@ -210,7 +257,8 @@ describe Rdkafka::Producer do
|
|
210
257
|
# Consume message and verify it's content
|
211
258
|
message = wait_for_message(
|
212
259
|
topic: "produce_test_topic",
|
213
|
-
delivery_report: report
|
260
|
+
delivery_report: report,
|
261
|
+
consumer: consumer
|
214
262
|
)
|
215
263
|
|
216
264
|
expect(message.key).to eq "key no payload"
|
@@ -229,7 +277,8 @@ describe Rdkafka::Producer do
|
|
229
277
|
# Consume message and verify it's content
|
230
278
|
message = wait_for_message(
|
231
279
|
topic: "produce_test_topic",
|
232
|
-
delivery_report: report
|
280
|
+
delivery_report: report,
|
281
|
+
consumer: consumer
|
233
282
|
)
|
234
283
|
|
235
284
|
expect(message.payload).to eq "payload headers"
|
@@ -251,7 +300,8 @@ describe Rdkafka::Producer do
|
|
251
300
|
# Consume message and verify it's content
|
252
301
|
message = wait_for_message(
|
253
302
|
topic: "produce_test_topic",
|
254
|
-
delivery_report: report
|
303
|
+
delivery_report: report,
|
304
|
+
consumer: consumer
|
255
305
|
)
|
256
306
|
|
257
307
|
expect(message.payload).to eq "payload headers"
|
@@ -284,11 +334,17 @@ describe Rdkafka::Producer do
|
|
284
334
|
# Fork, produce a message, send the report over a pipe and
|
285
335
|
# wait for and check the message in the main process.
|
286
336
|
|
337
|
+
# Kernel#fork is not available in JRuby
|
338
|
+
skip if defined?(JRUBY_VERSION)
|
339
|
+
|
287
340
|
reader, writer = IO.pipe
|
288
341
|
|
289
342
|
fork do
|
290
343
|
reader.close
|
291
344
|
|
345
|
+
# Avoids sharing the socket between processes.
|
346
|
+
producer = rdkafka_config.producer
|
347
|
+
|
292
348
|
handle = producer.produce(
|
293
349
|
topic: "produce_test_topic",
|
294
350
|
payload: "payload-forked",
|
@@ -296,7 +352,6 @@ describe Rdkafka::Producer do
|
|
296
352
|
)
|
297
353
|
|
298
354
|
report = handle.wait(max_wait_timeout: 5)
|
299
|
-
producer.close
|
300
355
|
|
301
356
|
report_json = JSON.generate(
|
302
357
|
"partition" => report.partition,
|
@@ -304,20 +359,24 @@ describe Rdkafka::Producer do
|
|
304
359
|
)
|
305
360
|
|
306
361
|
writer.write(report_json)
|
362
|
+
writer.close
|
363
|
+
producer.close
|
307
364
|
end
|
308
365
|
|
309
366
|
writer.close
|
310
|
-
|
311
367
|
report_hash = JSON.parse(reader.read)
|
312
368
|
report = Rdkafka::Producer::DeliveryReport.new(
|
313
369
|
report_hash["partition"],
|
314
370
|
report_hash["offset"]
|
315
371
|
)
|
316
372
|
|
373
|
+
reader.close
|
374
|
+
|
317
375
|
# Consume message and verify it's content
|
318
376
|
message = wait_for_message(
|
319
377
|
topic: "produce_test_topic",
|
320
|
-
delivery_report: report
|
378
|
+
delivery_report: report,
|
379
|
+
consumer: consumer
|
321
380
|
)
|
322
381
|
expect(message.partition).to eq 0
|
323
382
|
expect(message.payload).to eq "payload-forked"
|
data/spec/spec_helper.rb
CHANGED
@@ -7,6 +7,14 @@ require "pry"
|
|
7
7
|
require "rspec"
|
8
8
|
require "rdkafka"
|
9
9
|
|
10
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --if-not-exists --topic consume_test_topic`
|
11
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --if-not-exists --topic empty_test_topic`
|
12
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --if-not-exists --topic load_test_topic`
|
13
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --if-not-exists --topic produce_test_topic`
|
14
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --if-not-exists --topic rake_test_topic`
|
15
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --if-not-exists --topic watermarks_test_topic`
|
16
|
+
`docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 25 --if-not-exists --topic partitioner_test_topic`
|
17
|
+
|
10
18
|
def rdkafka_config(config_overrides={})
|
11
19
|
config = {
|
12
20
|
:"api.version.request" => false,
|
@@ -25,12 +33,12 @@ def rdkafka_config(config_overrides={})
|
|
25
33
|
Rdkafka::Config.new(config)
|
26
34
|
end
|
27
35
|
|
28
|
-
def
|
36
|
+
def new_native_client
|
29
37
|
config = rdkafka_config
|
30
38
|
config.send(:native_kafka, config.send(:native_config), :rd_kafka_producer)
|
31
39
|
end
|
32
40
|
|
33
|
-
def new_native_topic(topic_name="topic_name")
|
41
|
+
def new_native_topic(topic_name="topic_name", native_client: )
|
34
42
|
Rdkafka::Bindings.rd_kafka_topic_new(
|
35
43
|
native_client,
|
36
44
|
topic_name,
|
@@ -39,7 +47,8 @@ def new_native_topic(topic_name="topic_name")
|
|
39
47
|
end
|
40
48
|
|
41
49
|
def wait_for_message(topic:, delivery_report:, timeout_in_seconds: 30, consumer: nil)
|
42
|
-
|
50
|
+
new_consumer = !!consumer
|
51
|
+
consumer ||= rdkafka_config.consumer
|
43
52
|
consumer.subscribe(topic)
|
44
53
|
timeout = Time.now.to_i + timeout_in_seconds
|
45
54
|
loop do
|
@@ -53,6 +62,8 @@ def wait_for_message(topic:, delivery_report:, timeout_in_seconds: 30, consumer:
|
|
53
62
|
return message
|
54
63
|
end
|
55
64
|
end
|
65
|
+
ensure
|
66
|
+
consumer.close if new_consumer
|
56
67
|
end
|
57
68
|
|
58
69
|
def wait_for_assignment(consumer)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdkafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thijs Cadier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -42,14 +42,14 @@ dependencies:
|
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '12.3'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '12.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- lib/rdkafka/consumer/partition.rb
|
137
137
|
- lib/rdkafka/consumer/topic_partition_list.rb
|
138
138
|
- lib/rdkafka/error.rb
|
139
|
+
- lib/rdkafka/metadata.rb
|
139
140
|
- lib/rdkafka/producer.rb
|
140
141
|
- lib/rdkafka/producer/delivery_handle.rb
|
141
142
|
- lib/rdkafka/producer/delivery_report.rb
|
@@ -167,12 +168,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
167
168
|
version: '2.4'
|
168
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
170
|
requirements:
|
170
|
-
- - "
|
171
|
+
- - ">"
|
171
172
|
- !ruby/object:Gem::Version
|
172
|
-
version:
|
173
|
+
version: 1.3.1
|
173
174
|
requirements: []
|
174
|
-
|
175
|
-
rubygems_version: 2.7.6.2
|
175
|
+
rubygems_version: 3.1.2
|
176
176
|
signing_key:
|
177
177
|
specification_version: 4
|
178
178
|
summary: The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka.
|