rdkafka 0.12.0 → 0.13.0.beta.3

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.semaphore/semaphore.yml +6 -2
  3. data/CHANGELOG.md +12 -0
  4. data/Gemfile +2 -0
  5. data/Rakefile +2 -0
  6. data/ext/Rakefile +2 -0
  7. data/lib/rdkafka/abstract_handle.rb +2 -0
  8. data/lib/rdkafka/admin/create_topic_handle.rb +2 -0
  9. data/lib/rdkafka/admin/create_topic_report.rb +2 -0
  10. data/lib/rdkafka/admin/delete_topic_handle.rb +2 -0
  11. data/lib/rdkafka/admin/delete_topic_report.rb +2 -0
  12. data/lib/rdkafka/admin.rb +40 -35
  13. data/lib/rdkafka/bindings.rb +22 -6
  14. data/lib/rdkafka/callbacks.rb +7 -1
  15. data/lib/rdkafka/config.rb +9 -6
  16. data/lib/rdkafka/consumer/headers.rb +24 -7
  17. data/lib/rdkafka/consumer/message.rb +3 -1
  18. data/lib/rdkafka/consumer/partition.rb +2 -0
  19. data/lib/rdkafka/consumer/topic_partition_list.rb +2 -0
  20. data/lib/rdkafka/consumer.rb +37 -29
  21. data/lib/rdkafka/error.rb +9 -0
  22. data/lib/rdkafka/metadata.rb +2 -0
  23. data/lib/rdkafka/native_kafka.rb +62 -0
  24. data/lib/rdkafka/producer/delivery_handle.rb +5 -2
  25. data/lib/rdkafka/producer/delivery_report.rb +9 -2
  26. data/lib/rdkafka/producer.rb +23 -10
  27. data/lib/rdkafka/version.rb +5 -3
  28. data/lib/rdkafka.rb +3 -1
  29. data/rdkafka.gemspec +2 -0
  30. data/spec/rdkafka/abstract_handle_spec.rb +2 -0
  31. data/spec/rdkafka/admin/create_topic_handle_spec.rb +2 -0
  32. data/spec/rdkafka/admin/create_topic_report_spec.rb +2 -0
  33. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +2 -0
  34. data/spec/rdkafka/admin/delete_topic_report_spec.rb +2 -0
  35. data/spec/rdkafka/admin_spec.rb +4 -3
  36. data/spec/rdkafka/bindings_spec.rb +2 -0
  37. data/spec/rdkafka/callbacks_spec.rb +2 -0
  38. data/spec/rdkafka/config_spec.rb +14 -0
  39. data/spec/rdkafka/consumer/headers_spec.rb +62 -0
  40. data/spec/rdkafka/consumer/message_spec.rb +3 -1
  41. data/spec/rdkafka/consumer/partition_spec.rb +2 -0
  42. data/spec/rdkafka/consumer/topic_partition_list_spec.rb +2 -0
  43. data/spec/rdkafka/consumer_spec.rb +84 -15
  44. data/spec/rdkafka/error_spec.rb +2 -0
  45. data/spec/rdkafka/metadata_spec.rb +3 -1
  46. data/spec/rdkafka/{producer/client_spec.rb → native_kafka_spec.rb} +22 -10
  47. data/spec/rdkafka/producer/delivery_handle_spec.rb +5 -0
  48. data/spec/rdkafka/producer/delivery_report_spec.rb +8 -2
  49. data/spec/rdkafka/producer_spec.rb +51 -19
  50. data/spec/spec_helper.rb +16 -0
  51. metadata +13 -11
  52. data/lib/rdkafka/producer/client.rb +0 -47
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
4
  # A consumer of Kafka messages. It uses the high-level consumer approach where the Kafka
3
5
  # brokers automatically assign partitions and load balance partitions over consumers that
@@ -14,18 +16,24 @@ module Rdkafka
14
16
  # @private
15
17
  def initialize(native_kafka)
16
18
  @native_kafka = native_kafka
17
- @closing = false
19
+ end
20
+
21
+ def finalizer
22
+ ->(_) { close }
18
23
  end
19
24
 
20
25
  # Close this consumer
21
26
  # @return [nil]
22
27
  def close
23
- return unless @native_kafka
28
+ return if closed?
29
+ ObjectSpace.undefine_finalizer(self)
30
+ Rdkafka::Bindings.rd_kafka_consumer_close(@native_kafka.inner)
31
+ @native_kafka.close
32
+ end
24
33
 
25
- @closing = true
26
- Rdkafka::Bindings.rd_kafka_consumer_close(@native_kafka)
27
- Rdkafka::Bindings.rd_kafka_destroy(@native_kafka)
28
- @native_kafka = nil
34
+ # Whether this consumer has closed
35
+ def closed?
36
+ @native_kafka.closed?
29
37
  end
30
38
 
31
39
  # Subscribe to one or more topics letting Kafka handle partition assignments.
@@ -46,7 +54,7 @@ module Rdkafka
46
54
  end
47
55
 
48
56
  # Subscribe to topic partition list and check this was successful
49
- response = Rdkafka::Bindings.rd_kafka_subscribe(@native_kafka, tpl)
57
+ response = Rdkafka::Bindings.rd_kafka_subscribe(@native_kafka.inner, tpl)
50
58
  if response != 0
51
59
  raise Rdkafka::RdkafkaError.new(response, "Error subscribing to '#{topics.join(', ')}'")
52
60
  end
@@ -62,7 +70,7 @@ module Rdkafka
62
70
  def unsubscribe
63
71
  closed_consumer_check(__method__)
64
72
 
65
- response = Rdkafka::Bindings.rd_kafka_unsubscribe(@native_kafka)
73
+ response = Rdkafka::Bindings.rd_kafka_unsubscribe(@native_kafka.inner)
66
74
  if response != 0
67
75
  raise Rdkafka::RdkafkaError.new(response)
68
76
  end
@@ -85,7 +93,7 @@ module Rdkafka
85
93
  tpl = list.to_native_tpl
86
94
 
87
95
  begin
88
- response = Rdkafka::Bindings.rd_kafka_pause_partitions(@native_kafka, tpl)
96
+ response = Rdkafka::Bindings.rd_kafka_pause_partitions(@native_kafka.inner, tpl)
89
97
 
90
98
  if response != 0
91
99
  list = TopicPartitionList.from_native_tpl(tpl)
@@ -113,7 +121,7 @@ module Rdkafka
113
121
  tpl = list.to_native_tpl
114
122
 
115
123
  begin
116
- response = Rdkafka::Bindings.rd_kafka_resume_partitions(@native_kafka, tpl)
124
+ response = Rdkafka::Bindings.rd_kafka_resume_partitions(@native_kafka.inner, tpl)
117
125
  if response != 0
118
126
  raise Rdkafka::RdkafkaError.new(response, "Error resume '#{list.to_h}'")
119
127
  end
@@ -131,7 +139,7 @@ module Rdkafka
131
139
  closed_consumer_check(__method__)
132
140
 
133
141
  ptr = FFI::MemoryPointer.new(:pointer)
134
- response = Rdkafka::Bindings.rd_kafka_subscription(@native_kafka, ptr)
142
+ response = Rdkafka::Bindings.rd_kafka_subscription(@native_kafka.inner, ptr)
135
143
 
136
144
  if response != 0
137
145
  raise Rdkafka::RdkafkaError.new(response)
@@ -161,7 +169,7 @@ module Rdkafka
161
169
  tpl = list.to_native_tpl
162
170
 
163
171
  begin
164
- response = Rdkafka::Bindings.rd_kafka_assign(@native_kafka, tpl)
172
+ response = Rdkafka::Bindings.rd_kafka_assign(@native_kafka.inner, tpl)
165
173
  if response != 0
166
174
  raise Rdkafka::RdkafkaError.new(response, "Error assigning '#{list.to_h}'")
167
175
  end
@@ -179,7 +187,7 @@ module Rdkafka
179
187
  closed_consumer_check(__method__)
180
188
 
181
189
  ptr = FFI::MemoryPointer.new(:pointer)
182
- response = Rdkafka::Bindings.rd_kafka_assignment(@native_kafka, ptr)
190
+ response = Rdkafka::Bindings.rd_kafka_assignment(@native_kafka.inner, ptr)
183
191
  if response != 0
184
192
  raise Rdkafka::RdkafkaError.new(response)
185
193
  end
@@ -218,7 +226,7 @@ module Rdkafka
218
226
  tpl = list.to_native_tpl
219
227
 
220
228
  begin
221
- response = Rdkafka::Bindings.rd_kafka_committed(@native_kafka, tpl, timeout_ms)
229
+ response = Rdkafka::Bindings.rd_kafka_committed(@native_kafka.inner, tpl, timeout_ms)
222
230
  if response != 0
223
231
  raise Rdkafka::RdkafkaError.new(response)
224
232
  end
@@ -244,7 +252,7 @@ module Rdkafka
244
252
  high = FFI::MemoryPointer.new(:int64, 1)
245
253
 
246
254
  response = Rdkafka::Bindings.rd_kafka_query_watermark_offsets(
247
- @native_kafka,
255
+ @native_kafka.inner,
248
256
  topic,
249
257
  partition,
250
258
  low,
@@ -298,7 +306,7 @@ module Rdkafka
298
306
  # @return [String, nil]
299
307
  def cluster_id
300
308
  closed_consumer_check(__method__)
301
- Rdkafka::Bindings.rd_kafka_clusterid(@native_kafka)
309
+ Rdkafka::Bindings.rd_kafka_clusterid(@native_kafka.inner)
302
310
  end
303
311
 
304
312
  # Returns this client's broker-assigned group member id
@@ -308,7 +316,7 @@ module Rdkafka
308
316
  # @return [String, nil]
309
317
  def member_id
310
318
  closed_consumer_check(__method__)
311
- Rdkafka::Bindings.rd_kafka_memberid(@native_kafka)
319
+ Rdkafka::Bindings.rd_kafka_memberid(@native_kafka.inner)
312
320
  end
313
321
 
314
322
  # Store offset of a message to be used in the next commit of this consumer
@@ -326,7 +334,7 @@ module Rdkafka
326
334
  # rd_kafka_offset_store is one of the few calls that does not support
327
335
  # a string as the topic, so create a native topic for it.
328
336
  native_topic = Rdkafka::Bindings.rd_kafka_topic_new(
329
- @native_kafka,
337
+ @native_kafka.inner,
330
338
  message.topic,
331
339
  nil
332
340
  )
@@ -358,7 +366,7 @@ module Rdkafka
358
366
  # rd_kafka_offset_store is one of the few calls that does not support
359
367
  # a string as the topic, so create a native topic for it.
360
368
  native_topic = Rdkafka::Bindings.rd_kafka_topic_new(
361
- @native_kafka,
369
+ @native_kafka.inner,
362
370
  message.topic,
363
371
  nil
364
372
  )
@@ -402,7 +410,7 @@ module Rdkafka
402
410
  tpl = list ? list.to_native_tpl : nil
403
411
 
404
412
  begin
405
- response = Rdkafka::Bindings.rd_kafka_commit(@native_kafka, tpl, async)
413
+ response = Rdkafka::Bindings.rd_kafka_commit(@native_kafka.inner, tpl, async)
406
414
  if response != 0
407
415
  raise Rdkafka::RdkafkaError.new(response)
408
416
  end
@@ -421,7 +429,7 @@ module Rdkafka
421
429
  def poll(timeout_ms)
422
430
  closed_consumer_check(__method__)
423
431
 
424
- message_ptr = Rdkafka::Bindings.rd_kafka_consumer_poll(@native_kafka, timeout_ms)
432
+ message_ptr = Rdkafka::Bindings.rd_kafka_consumer_poll(@native_kafka.inner, timeout_ms)
425
433
  if message_ptr.null?
426
434
  nil
427
435
  else
@@ -436,7 +444,7 @@ module Rdkafka
436
444
  end
437
445
  ensure
438
446
  # Clean up rdkafka message if there is one
439
- if !message_ptr.nil? && !message_ptr.null?
447
+ if message_ptr && !message_ptr.null?
440
448
  Rdkafka::Bindings.rd_kafka_message_destroy(message_ptr)
441
449
  end
442
450
  end
@@ -459,7 +467,7 @@ module Rdkafka
459
467
  if message
460
468
  yield(message)
461
469
  else
462
- if @closing
470
+ if closed?
463
471
  break
464
472
  else
465
473
  next
@@ -468,10 +476,6 @@ module Rdkafka
468
476
  end
469
477
  end
470
478
 
471
- def closed_consumer_check(method)
472
- raise Rdkafka::ClosedConsumerError.new(method) if @native_kafka.nil?
473
- end
474
-
475
479
  # Poll for new messages and yield them in batches that may contain
476
480
  # messages from more than one partition.
477
481
  #
@@ -527,7 +531,7 @@ module Rdkafka
527
531
  bytes = 0
528
532
  end_time = monotonic_now + timeout_ms / 1000.0
529
533
  loop do
530
- break if @closing
534
+ break if closed?
531
535
  max_wait = end_time - monotonic_now
532
536
  max_wait_ms = if max_wait <= 0
533
537
  0 # should not block, but may retrieve a message
@@ -545,7 +549,7 @@ module Rdkafka
545
549
  end
546
550
  if message
547
551
  slice << message
548
- bytes += message.payload.bytesize
552
+ bytes += message.payload.bytesize if message.payload
549
553
  end
550
554
  if slice.size == max_items || bytes >= bytes_threshold || monotonic_now >= end_time - 0.001
551
555
  yield slice.dup, nil
@@ -561,5 +565,9 @@ module Rdkafka
561
565
  # needed because Time.now can go backwards
562
566
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
563
567
  end
568
+
569
+ def closed_consumer_check(method)
570
+ raise Rdkafka::ClosedConsumerError.new(method) if closed?
571
+ end
564
572
  end
565
573
  end
data/lib/rdkafka/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
4
  # Base error class.
3
5
  class BaseError < RuntimeError; end
@@ -83,4 +85,11 @@ module Rdkafka
83
85
  super("Illegal call to #{method.to_s} on a closed producer")
84
86
  end
85
87
  end
88
+
89
+ # Error class for public consumer method calls on a closed admin.
90
+ class ClosedAdminError < BaseError
91
+ def initialize(method)
92
+ super("Illegal call to #{method.to_s} on a closed admin")
93
+ end
94
+ end
86
95
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
4
  class Metadata
3
5
  attr_reader :brokers, :topics
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rdkafka
4
+ # @private
5
+ # A wrapper around a native kafka that polls and cleanly exits
6
+ class NativeKafka
7
+ def initialize(inner, run_polling_thread:)
8
+ @inner = inner
9
+
10
+ if run_polling_thread
11
+ # Start thread to poll client for delivery callbacks,
12
+ # not used in consumer.
13
+ @polling_thread = Thread.new do
14
+ loop do
15
+ Rdkafka::Bindings.rd_kafka_poll(inner, 250)
16
+ # Exit thread if closing and the poll queue is empty
17
+ if Thread.current[:closing] && Rdkafka::Bindings.rd_kafka_outq_len(inner) == 0
18
+ break
19
+ end
20
+ end
21
+ end
22
+ @polling_thread.abort_on_exception = true
23
+ @polling_thread[:closing] = false
24
+ end
25
+
26
+ @closing = false
27
+ end
28
+
29
+ def inner
30
+ @inner
31
+ end
32
+
33
+ def finalizer
34
+ ->(_) { close }
35
+ end
36
+
37
+ def closed?
38
+ @closing || @inner.nil?
39
+ end
40
+
41
+ def close(object_id=nil)
42
+ return if closed?
43
+
44
+ # Indicate to the outside world that we are closing
45
+ @closing = true
46
+
47
+ if @polling_thread
48
+ # Indicate to polling thread that we're closing
49
+ @polling_thread[:closing] = true
50
+ # Wait for the polling thread to finish up
51
+ @polling_thread.join
52
+ end
53
+
54
+ # Destroy the client
55
+ Rdkafka::Bindings.rd_kafka_destroy_flags(
56
+ @inner,
57
+ Rdkafka::Bindings::RD_KAFKA_DESTROY_F_IMMEDIATE
58
+ )
59
+ @inner = nil
60
+ end
61
+ end
62
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
4
  class Producer
3
5
  # Handle to wait for a delivery report which is returned when
@@ -6,7 +8,8 @@ module Rdkafka
6
8
  layout :pending, :bool,
7
9
  :response, :int,
8
10
  :partition, :int,
9
- :offset, :int64
11
+ :offset, :int64,
12
+ :topic_name, :pointer
10
13
 
11
14
  # @return [String] the name of the operation (e.g. "delivery")
12
15
  def operation_name
@@ -15,7 +18,7 @@ module Rdkafka
15
18
 
16
19
  # @return [DeliveryReport] a report on the delivery of the message
17
20
  def create_result
18
- DeliveryReport.new(self[:partition], self[:offset])
21
+ DeliveryReport.new(self[:partition], self[:offset], self[:topic_name].read_string)
19
22
  end
20
23
  end
21
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
4
  class Producer
3
5
  # Delivery report for a successfully produced message.
@@ -10,15 +12,20 @@ module Rdkafka
10
12
  # @return [Integer]
11
13
  attr_reader :offset
12
14
 
13
- # Error in case happen during produce.
15
+ # The name of the topic this message was produced to.
14
16
  # @return [String]
17
+ attr_reader :topic_name
18
+
19
+ # Error in case happen during produce.
20
+ # @return [Integer]
15
21
  attr_reader :error
16
22
 
17
23
  private
18
24
 
19
- def initialize(partition, offset, error = nil)
25
+ def initialize(partition, offset, topic_name = nil, error = nil)
20
26
  @partition = partition
21
27
  @offset = offset
28
+ @topic_name = topic_name
22
29
  @error = error
23
30
  end
24
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "objspace"
2
4
 
3
5
  module Rdkafka
@@ -16,12 +18,12 @@ module Rdkafka
16
18
  attr_reader :delivery_callback_arity
17
19
 
18
20
  # @private
19
- def initialize(client, partitioner_name)
20
- @client = client
21
+ def initialize(native_kafka, partitioner_name)
22
+ @native_kafka = native_kafka
21
23
  @partitioner_name = partitioner_name || "consistent_random"
22
24
 
23
- # Makes sure, that the producer gets closed before it gets GCed by Ruby
24
- ObjectSpace.define_finalizer(self, client.finalizer)
25
+ # Makes sure, that native kafka gets closed before it gets GCed by Ruby
26
+ ObjectSpace.define_finalizer(self, native_kafka.finalizer)
25
27
  end
26
28
 
27
29
  # Set a callback that will be called every time a message is successfully produced.
@@ -38,9 +40,21 @@ module Rdkafka
38
40
 
39
41
  # Close this producer and wait for the internal poll queue to empty.
40
42
  def close
43
+ return if closed?
41
44
  ObjectSpace.undefine_finalizer(self)
45
+ @native_kafka.close
46
+ end
42
47
 
43
- @client.close
48
+ # Whether this producer has closed
49
+ def closed?
50
+ @native_kafka.closed?
51
+ end
52
+
53
+ # Wait until all outstanding producer requests are completed, with the given timeout
54
+ # in seconds. Call this before closing a producer to ensure delivery of all messages.
55
+ def flush(timeout_ms=5_000)
56
+ closed_producer_check(__method__)
57
+ Rdkafka::Bindings.rd_kafka_flush(@native_kafka.inner, timeout_ms)
44
58
  end
45
59
 
46
60
  # Partition count for a given topic.
@@ -49,10 +63,9 @@ module Rdkafka
49
63
  # @param topic [String] The topic name.
50
64
  #
51
65
  # @return partition count [Integer,nil]
52
- #
53
66
  def partition_count(topic)
54
67
  closed_producer_check(__method__)
55
- Rdkafka::Metadata.new(@client.native, topic).topics&.first[:partition_count]
68
+ Rdkafka::Metadata.new(@native_kafka.inner, topic).topics&.first[:partition_count]
56
69
  end
57
70
 
58
71
  # Produces a message to a Kafka topic. The message is added to rdkafka's queue, call {DeliveryHandle#wait wait} on the returned delivery handle to make sure it is delivered.
@@ -144,7 +157,7 @@ module Rdkafka
144
157
 
145
158
  # Produce the message
146
159
  response = Rdkafka::Bindings.rd_kafka_producev(
147
- @client.native,
160
+ @native_kafka.inner,
148
161
  *args
149
162
  )
150
163
 
@@ -157,7 +170,6 @@ module Rdkafka
157
170
  delivery_handle
158
171
  end
159
172
 
160
- # @private
161
173
  def call_delivery_callback(delivery_report, delivery_handle)
162
174
  return unless @delivery_callback
163
175
 
@@ -171,8 +183,9 @@ module Rdkafka
171
183
  callback.method(:call).arity
172
184
  end
173
185
 
186
+ private
174
187
  def closed_producer_check(method)
175
- raise Rdkafka::ClosedProducerError.new(method) if @client.closed?
188
+ raise Rdkafka::ClosedProducerError.new(method) if closed?
176
189
  end
177
190
  end
178
191
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rdkafka
2
- VERSION = "0.12.0"
3
- LIBRDKAFKA_VERSION = "1.9.0"
4
- LIBRDKAFKA_SOURCE_SHA256 = "59b6088b69ca6cf278c3f9de5cd6b7f3fd604212cd1c59870bc531c54147e889"
4
+ VERSION = "0.13.0.beta.3"
5
+ LIBRDKAFKA_VERSION = "1.9.2"
6
+ LIBRDKAFKA_SOURCE_SHA256 = "3fba157a9f80a0889c982acdd44608be8a46142270a389008b22d921be1198ad"
5
7
  end
data/lib/rdkafka.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rdkafka/version"
2
4
 
3
5
  require "rdkafka/abstract_handle"
@@ -16,7 +18,7 @@ require "rdkafka/consumer/partition"
16
18
  require "rdkafka/consumer/topic_partition_list"
17
19
  require "rdkafka/error"
18
20
  require "rdkafka/metadata"
21
+ require "rdkafka/native_kafka"
19
22
  require "rdkafka/producer"
20
- require "rdkafka/producer/client"
21
23
  require "rdkafka/producer/delivery_handle"
22
24
  require "rdkafka/producer/delivery_report"
data/rdkafka.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('lib/rdkafka/version', __dir__)
2
4
 
3
5
  Gem::Specification.new do |gem|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::AbstractHandle do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Admin::CreateTopicHandle do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Admin::CreateTopicReport do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Admin::DeleteTopicHandle do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Admin::DeleteTopicReport do
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
  require "ostruct"
3
5
 
4
6
  describe Rdkafka::Admin do
5
- let(:config) { rdkafka_config }
6
- let(:admin) { config.admin }
7
+ let(:config) { rdkafka_config }
8
+ let(:admin) { config.admin }
7
9
 
8
10
  after do
9
11
  # Registry should always end up being empty
@@ -174,7 +176,6 @@ describe Rdkafka::Admin do
174
176
  end
175
177
  end
176
178
 
177
-
178
179
  it "deletes a topic that was newly created" do
179
180
  create_topic_handle = admin.create_topic(topic_name, topic_partition_count, topic_replication_factor)
180
181
  create_topic_report = create_topic_handle.wait(max_wait_timeout: 15.0)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
  require 'zlib'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Callbacks do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Config do
@@ -148,6 +150,18 @@ describe Rdkafka::Config do
148
150
  }.to raise_error(Rdkafka::Config::ConfigError, "No such configuration property: \"invalid.key\"")
149
151
  end
150
152
 
153
+ it "allows string partitioner key" do
154
+ expect(Rdkafka::Producer).to receive(:new).with(kind_of(Rdkafka::NativeKafka), "murmur2")
155
+ config = Rdkafka::Config.new("partitioner" => "murmur2")
156
+ config.producer
157
+ end
158
+
159
+ it "allows symbol partitioner key" do
160
+ expect(Rdkafka::Producer).to receive(:new).with(kind_of(Rdkafka::NativeKafka), "murmur2")
161
+ config = Rdkafka::Config.new(:partitioner => "murmur2")
162
+ config.producer
163
+ end
164
+
151
165
  it "should allow configuring zstd compression" do
152
166
  config = Rdkafka::Config.new('compression.codec' => 'zstd')
153
167
  begin
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Rdkafka::Consumer::Headers do
6
+ let(:headers) do
7
+ { # Note String keys!
8
+ "version" => "2.1.3",
9
+ "type" => "String"
10
+ }
11
+ end
12
+ let(:native_message) { double('native message') }
13
+ let(:headers_ptr) { double('headers pointer') }
14
+
15
+ describe '.from_native' do
16
+ before do
17
+ expect(Rdkafka::Bindings).to receive(:rd_kafka_message_headers).with(native_message, anything) do |_, headers_ptrptr|
18
+ expect(headers_ptrptr).to receive(:read_pointer).and_return(headers_ptr)
19
+ Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
20
+ end
21
+
22
+ expect(Rdkafka::Bindings).to \
23
+ receive(:rd_kafka_header_get_all)
24
+ .with(headers_ptr, 0, anything, anything, anything) do |_, _, name_ptrptr, value_ptrptr, size_ptr|
25
+ expect(name_ptrptr).to receive(:read_pointer).and_return(double("pointer 0", read_string_to_null: headers.keys[0]))
26
+ expect(size_ptr).to receive(:[]).with(:value).and_return(headers.keys[0].size)
27
+ expect(value_ptrptr).to receive(:read_pointer).and_return(double("value pointer 0", read_string: headers.values[0]))
28
+ Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
29
+ end
30
+
31
+ expect(Rdkafka::Bindings).to \
32
+ receive(:rd_kafka_header_get_all)
33
+ .with(headers_ptr, 1, anything, anything, anything) do |_, _, name_ptrptr, value_ptrptr, size_ptr|
34
+ expect(name_ptrptr).to receive(:read_pointer).and_return(double("pointer 1", read_string_to_null: headers.keys[1]))
35
+ expect(size_ptr).to receive(:[]).with(:value).and_return(headers.keys[1].size)
36
+ expect(value_ptrptr).to receive(:read_pointer).and_return(double("value pointer 1", read_string: headers.values[1]))
37
+ Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
38
+ end
39
+
40
+ expect(Rdkafka::Bindings).to \
41
+ receive(:rd_kafka_header_get_all)
42
+ .with(headers_ptr, 2, anything, anything, anything)
43
+ .and_return(Rdkafka::Bindings::RD_KAFKA_RESP_ERR__NOENT)
44
+ end
45
+
46
+ subject { described_class.from_native(native_message) }
47
+
48
+ it { is_expected.to eq(headers) }
49
+ it { is_expected.to be_frozen }
50
+
51
+ it 'allows String key' do
52
+ expect(subject['version']).to eq("2.1.3")
53
+ end
54
+
55
+ it 'allows Symbol key, but warns' do
56
+ expect(Kernel).to \
57
+ receive(:warn).with("rdkafka deprecation warning: header access with Symbol key :version treated as a String. " \
58
+ "Please change your code to use String keys to avoid this warning. Symbol keys will break in version 1.")
59
+ expect(subject[:version]).to eq("2.1.3")
60
+ end
61
+ end
62
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Consumer::Message do
@@ -26,7 +28,7 @@ describe Rdkafka::Consumer::Message do
26
28
  end
27
29
 
28
30
  after(:each) do
29
- Rdkafka::Bindings.rd_kafka_destroy(native_client)
31
+ Rdkafka::Bindings.rd_kafka_destroy_flags(native_client, Rdkafka::Bindings::RD_KAFKA_DESTROY_F_IMMEDIATE)
30
32
  end
31
33
 
32
34
  subject { Rdkafka::Consumer::Message.new(native_message) }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Consumer::Partition do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Rdkafka::Consumer::TopicPartitionList do