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.
@@ -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.