rdkafka 0.7.0 → 0.8.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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).to eq Rdkafka::RdkafkaError.new(20, "Error explanation")
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).to eq Rdkafka::RdkafkaError.new(10, "Different error explanation")
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).to eq Rdkafka::RdkafkaError.new(10)
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: 5)
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, "missing keyword: topic"
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(5).of(Time.now)
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 native_client
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
- consumer = rdkafka_config.consumer if consumer.nil?
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.7.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: 2019-09-21 00:00:00.000000000 Z
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: '0'
173
+ version: 1.3.1
173
174
  requirements: []
174
- rubyforge_project:
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.