rdkafka 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.semaphore/semaphore.yml +23 -0
  3. data/CHANGELOG.md +6 -0
  4. data/README.md +5 -2
  5. data/docker-compose.yml +2 -0
  6. data/ext/Rakefile +1 -1
  7. data/lib/rdkafka.rb +7 -0
  8. data/lib/rdkafka/abstract_handle.rb +82 -0
  9. data/lib/rdkafka/admin.rb +144 -0
  10. data/lib/rdkafka/admin/create_topic_handle.rb +27 -0
  11. data/lib/rdkafka/admin/create_topic_report.rb +22 -0
  12. data/lib/rdkafka/admin/delete_topic_handle.rb +27 -0
  13. data/lib/rdkafka/admin/delete_topic_report.rb +22 -0
  14. data/lib/rdkafka/bindings.rb +44 -17
  15. data/lib/rdkafka/callbacks.rb +106 -0
  16. data/lib/rdkafka/config.rb +14 -1
  17. data/lib/rdkafka/consumer.rb +35 -5
  18. data/lib/rdkafka/error.rb +29 -3
  19. data/lib/rdkafka/metadata.rb +6 -5
  20. data/lib/rdkafka/producer.rb +13 -2
  21. data/lib/rdkafka/producer/delivery_handle.rb +7 -53
  22. data/lib/rdkafka/version.rb +1 -1
  23. data/spec/rdkafka/abstract_handle_spec.rb +114 -0
  24. data/spec/rdkafka/admin/create_topic_handle_spec.rb +52 -0
  25. data/spec/rdkafka/admin/create_topic_report_spec.rb +16 -0
  26. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +52 -0
  27. data/spec/rdkafka/admin/delete_topic_report_spec.rb +16 -0
  28. data/spec/rdkafka/admin_spec.rb +192 -0
  29. data/spec/rdkafka/callbacks_spec.rb +20 -0
  30. data/spec/rdkafka/config_spec.rb +11 -0
  31. data/spec/rdkafka/consumer_spec.rb +34 -2
  32. data/spec/rdkafka/error_spec.rb +4 -0
  33. data/spec/rdkafka/metadata_spec.rb +78 -0
  34. data/spec/rdkafka/producer/delivery_handle_spec.rb +1 -41
  35. data/spec/rdkafka/producer_spec.rb +22 -0
  36. data/spec/spec_helper.rb +28 -11
  37. metadata +26 -3
  38. data/.travis.yml +0 -48
@@ -0,0 +1,106 @@
1
+ module Rdkafka
2
+ module Callbacks
3
+
4
+ # Extracts attributes of a rd_kafka_topic_result_t
5
+ #
6
+ # @private
7
+ class TopicResult
8
+ attr_reader :result_error, :error_string, :result_name
9
+
10
+ def initialize(topic_result_pointer)
11
+ @result_error = Rdkafka::Bindings.rd_kafka_topic_result_error(topic_result_pointer)
12
+ @error_string = Rdkafka::Bindings.rd_kafka_topic_result_error_string(topic_result_pointer)
13
+ @result_name = Rdkafka::Bindings.rd_kafka_topic_result_name(topic_result_pointer)
14
+ end
15
+
16
+ def self.create_topic_results_from_array(count, array_pointer)
17
+ (1..count).map do |index|
18
+ result_pointer = (array_pointer + (index - 1)).read_pointer
19
+ new(result_pointer)
20
+ end
21
+ end
22
+ end
23
+
24
+ # FFI Function used for Create Topic and Delete Topic callbacks
25
+ BackgroundEventCallbackFunction = FFI::Function.new(
26
+ :void, [:pointer, :pointer, :pointer]
27
+ ) do |client_ptr, event_ptr, opaque_ptr|
28
+ BackgroundEventCallback.call(client_ptr, event_ptr, opaque_ptr)
29
+ end
30
+
31
+ # @private
32
+ class BackgroundEventCallback
33
+ def self.call(_, event_ptr, _)
34
+ event_type = Rdkafka::Bindings.rd_kafka_event_type(event_ptr)
35
+ if event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_CREATETOPICS_RESULT
36
+ process_create_topic(event_ptr)
37
+ elsif event_type == Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT
38
+ process_delete_topic(event_ptr)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def self.process_create_topic(event_ptr)
45
+ create_topics_result = Rdkafka::Bindings.rd_kafka_event_CreateTopics_result(event_ptr)
46
+
47
+ # Get the number of create topic results
48
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
49
+ create_topic_result_array = Rdkafka::Bindings.rd_kafka_CreateTopics_result_topics(create_topics_result, pointer_to_size_t)
50
+ create_topic_results = TopicResult.create_topic_results_from_array(pointer_to_size_t.read_int, create_topic_result_array)
51
+ create_topic_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
52
+
53
+ if create_topic_handle = Rdkafka::Admin::CreateTopicHandle.remove(create_topic_handle_ptr.address)
54
+ create_topic_handle[:response] = create_topic_results[0].result_error
55
+ create_topic_handle[:error_string] = create_topic_results[0].error_string
56
+ create_topic_handle[:result_name] = create_topic_results[0].result_name
57
+ create_topic_handle[:pending] = false
58
+ end
59
+ end
60
+
61
+ def self.process_delete_topic(event_ptr)
62
+ delete_topics_result = Rdkafka::Bindings.rd_kafka_event_DeleteTopics_result(event_ptr)
63
+
64
+ # Get the number of topic results
65
+ pointer_to_size_t = FFI::MemoryPointer.new(:int32)
66
+ delete_topic_result_array = Rdkafka::Bindings.rd_kafka_DeleteTopics_result_topics(delete_topics_result, pointer_to_size_t)
67
+ delete_topic_results = TopicResult.create_topic_results_from_array(pointer_to_size_t.read_int, delete_topic_result_array)
68
+ delete_topic_handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
69
+
70
+ if delete_topic_handle = Rdkafka::Admin::DeleteTopicHandle.remove(delete_topic_handle_ptr.address)
71
+ delete_topic_handle[:response] = delete_topic_results[0].result_error
72
+ delete_topic_handle[:error_string] = delete_topic_results[0].error_string
73
+ delete_topic_handle[:result_name] = delete_topic_results[0].result_name
74
+ delete_topic_handle[:pending] = false
75
+ end
76
+ end
77
+ end
78
+
79
+ # FFI Function used for Message Delivery callbacks
80
+
81
+ DeliveryCallbackFunction = FFI::Function.new(
82
+ :void, [:pointer, :pointer, :pointer]
83
+ ) do |client_ptr, message_ptr, opaque_ptr|
84
+ DeliveryCallback.call(client_ptr, message_ptr, opaque_ptr)
85
+ end
86
+
87
+ # @private
88
+ class DeliveryCallback
89
+ def self.call(_, message_ptr, opaque_ptr)
90
+ message = Rdkafka::Bindings::Message.new(message_ptr)
91
+ delivery_handle_ptr_address = message[:_private].address
92
+ if delivery_handle = Rdkafka::Producer::DeliveryHandle.remove(delivery_handle_ptr_address)
93
+ # Update delivery handle
94
+ delivery_handle[:response] = message[:err]
95
+ delivery_handle[:partition] = message[:partition]
96
+ delivery_handle[:offset] = message[:offset]
97
+ delivery_handle[:pending] = false
98
+ # Call delivery callback on opaque
99
+ if opaque = Rdkafka::Config.opaques[opaque_ptr.to_i]
100
+ opaque.call_delivery_callback(Rdkafka::Producer::DeliveryReport.new(message[:partition], message[:offset], message[:err]))
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -137,13 +137,26 @@ module Rdkafka
137
137
  # Create Kafka config
138
138
  config = native_config(opaque)
139
139
  # Set callback to receive delivery reports on config
140
- Rdkafka::Bindings.rd_kafka_conf_set_dr_msg_cb(config, Rdkafka::Bindings::DeliveryCallback)
140
+ Rdkafka::Bindings.rd_kafka_conf_set_dr_msg_cb(config, Rdkafka::Callbacks::DeliveryCallbackFunction)
141
141
  # Return producer with Kafka client
142
142
  Rdkafka::Producer.new(native_kafka(config, :rd_kafka_producer)).tap do |producer|
143
143
  opaque.producer = producer
144
144
  end
145
145
  end
146
146
 
147
+ # Create an admin instance with this configuration.
148
+ #
149
+ # @raise [ConfigError] When the configuration contains invalid options
150
+ # @raise [ClientCreationError] When the native client cannot be created
151
+ #
152
+ # @return [Admin] The created admin instance
153
+ def admin
154
+ opaque = Opaque.new
155
+ config = native_config(opaque)
156
+ Rdkafka::Bindings.rd_kafka_conf_set_background_event_cb(config, Rdkafka::Callbacks::BackgroundEventCallbackFunction)
157
+ Rdkafka::Admin.new(native_kafka(config, :rd_kafka_producer))
158
+ end
159
+
147
160
  # Error that is returned by the underlying rdkafka error if an invalid configuration option is present.
148
161
  class ConfigError < RuntimeError; end
149
162
 
@@ -36,6 +36,8 @@ module Rdkafka
36
36
  #
37
37
  # @return [nil]
38
38
  def subscribe(*topics)
39
+ closed_consumer_check(__method__)
40
+
39
41
  # Create topic partition list with topics and no partition set
40
42
  tpl = Rdkafka::Bindings.rd_kafka_topic_partition_list_new(topics.length)
41
43
 
@@ -49,7 +51,7 @@ module Rdkafka
49
51
  raise Rdkafka::RdkafkaError.new(response, "Error subscribing to '#{topics.join(', ')}'")
50
52
  end
51
53
  ensure
52
- Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(tpl)
54
+ Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(tpl) unless tpl.nil?
53
55
  end
54
56
 
55
57
  # Unsubscribe from all subscribed topics.
@@ -58,6 +60,8 @@ module Rdkafka
58
60
  #
59
61
  # @return [nil]
60
62
  def unsubscribe
63
+ closed_consumer_check(__method__)
64
+
61
65
  response = Rdkafka::Bindings.rd_kafka_unsubscribe(@native_kafka)
62
66
  if response != 0
63
67
  raise Rdkafka::RdkafkaError.new(response)
@@ -72,6 +76,8 @@ module Rdkafka
72
76
  #
73
77
  # @return [nil]
74
78
  def pause(list)
79
+ closed_consumer_check(__method__)
80
+
75
81
  unless list.is_a?(TopicPartitionList)
76
82
  raise TypeError.new("list has to be a TopicPartitionList")
77
83
  end
@@ -98,6 +104,8 @@ module Rdkafka
98
104
  #
99
105
  # @return [nil]
100
106
  def resume(list)
107
+ closed_consumer_check(__method__)
108
+
101
109
  unless list.is_a?(TopicPartitionList)
102
110
  raise TypeError.new("list has to be a TopicPartitionList")
103
111
  end
@@ -120,6 +128,8 @@ module Rdkafka
120
128
  #
121
129
  # @return [TopicPartitionList]
122
130
  def subscription
131
+ closed_consumer_check(__method__)
132
+
123
133
  ptr = FFI::MemoryPointer.new(:pointer)
124
134
  response = Rdkafka::Bindings.rd_kafka_subscription(@native_kafka, ptr)
125
135
 
@@ -142,6 +152,8 @@ module Rdkafka
142
152
  #
143
153
  # @raise [RdkafkaError] When assigning fails
144
154
  def assign(list)
155
+ closed_consumer_check(__method__)
156
+
145
157
  unless list.is_a?(TopicPartitionList)
146
158
  raise TypeError.new("list has to be a TopicPartitionList")
147
159
  end
@@ -164,6 +176,8 @@ module Rdkafka
164
176
  #
165
177
  # @return [TopicPartitionList]
166
178
  def assignment
179
+ closed_consumer_check(__method__)
180
+
167
181
  ptr = FFI::MemoryPointer.new(:pointer)
168
182
  response = Rdkafka::Bindings.rd_kafka_assignment(@native_kafka, ptr)
169
183
  if response != 0
@@ -180,7 +194,7 @@ module Rdkafka
180
194
  end
181
195
  end
182
196
  ensure
183
- ptr.free
197
+ ptr.free unless ptr.nil?
184
198
  end
185
199
 
186
200
  # Return the current committed offset per partition for this consumer group.
@@ -193,6 +207,8 @@ module Rdkafka
193
207
  #
194
208
  # @return [TopicPartitionList]
195
209
  def committed(list=nil, timeout_ms=1200)
210
+ closed_consumer_check(__method__)
211
+
196
212
  if list.nil?
197
213
  list = assignment
198
214
  elsif !list.is_a?(TopicPartitionList)
@@ -222,6 +238,8 @@ module Rdkafka
222
238
  #
223
239
  # @return [Integer] The low and high watermark
224
240
  def query_watermark_offsets(topic, partition, timeout_ms=200)
241
+ closed_consumer_check(__method__)
242
+
225
243
  low = FFI::MemoryPointer.new(:int64, 1)
226
244
  high = FFI::MemoryPointer.new(:int64, 1)
227
245
 
@@ -239,8 +257,8 @@ module Rdkafka
239
257
 
240
258
  return low.read_array_of_int64(1).first, high.read_array_of_int64(1).first
241
259
  ensure
242
- low.free
243
- high.free
260
+ low.free unless low.nil?
261
+ high.free unless high.nil?
244
262
  end
245
263
 
246
264
  # Calculate the consumer lag per partition for the provided topic partition list.
@@ -279,6 +297,7 @@ module Rdkafka
279
297
  #
280
298
  # @return [String, nil]
281
299
  def cluster_id
300
+ closed_consumer_check(__method__)
282
301
  Rdkafka::Bindings.rd_kafka_clusterid(@native_kafka)
283
302
  end
284
303
 
@@ -288,6 +307,7 @@ module Rdkafka
288
307
  #
289
308
  # @return [String, nil]
290
309
  def member_id
310
+ closed_consumer_check(__method__)
291
311
  Rdkafka::Bindings.rd_kafka_memberid(@native_kafka)
292
312
  end
293
313
 
@@ -301,6 +321,8 @@ module Rdkafka
301
321
  #
302
322
  # @return [nil]
303
323
  def store_offset(message)
324
+ closed_consumer_check(__method__)
325
+
304
326
  # rd_kafka_offset_store is one of the few calls that does not support
305
327
  # a string as the topic, so create a native topic for it.
306
328
  native_topic = Rdkafka::Bindings.rd_kafka_topic_new(
@@ -331,6 +353,8 @@ module Rdkafka
331
353
  #
332
354
  # @return [nil]
333
355
  def seek(message)
356
+ closed_consumer_check(__method__)
357
+
334
358
  # rd_kafka_offset_store is one of the few calls that does not support
335
359
  # a string as the topic, so create a native topic for it.
336
360
  native_topic = Rdkafka::Bindings.rd_kafka_topic_new(
@@ -369,6 +393,8 @@ module Rdkafka
369
393
  #
370
394
  # @return [nil]
371
395
  def commit(list=nil, async=false)
396
+ closed_consumer_check(__method__)
397
+
372
398
  if !list.nil? && !list.is_a?(TopicPartitionList)
373
399
  raise TypeError.new("list has to be nil or a TopicPartitionList")
374
400
  end
@@ -393,7 +419,7 @@ module Rdkafka
393
419
  #
394
420
  # @return [Message, nil] A message or nil if there was no new message within the timeout
395
421
  def poll(timeout_ms)
396
- return unless @native_kafka
422
+ closed_consumer_check(__method__)
397
423
 
398
424
  message_ptr = Rdkafka::Bindings.rd_kafka_consumer_poll(@native_kafka, timeout_ms)
399
425
  if message_ptr.null?
@@ -441,5 +467,9 @@ module Rdkafka
441
467
  end
442
468
  end
443
469
  end
470
+
471
+ def closed_consumer_check(method)
472
+ raise Rdkafka::ClosedConsumerError.new(method) if @native_kafka.nil?
473
+ end
444
474
  end
445
475
  end
@@ -1,15 +1,27 @@
1
1
  module Rdkafka
2
+ # Base error class.
3
+ class BaseError < RuntimeError; end
4
+
2
5
  # Error returned by the underlying rdkafka library.
3
- class RdkafkaError < RuntimeError
6
+ class RdkafkaError < BaseError
4
7
  # The underlying raw error response
5
8
  # @return [Integer]
6
- attr_reader :rdkafka_response, :message_prefix
9
+ attr_reader :rdkafka_response
10
+
11
+ # Prefix to be used for human readable representation
12
+ # @return [String]
13
+ attr_reader :message_prefix
14
+
15
+ # Error message sent by the broker
16
+ # @return [String]
17
+ attr_reader :broker_message
7
18
 
8
19
  # @private
9
- def initialize(response, message_prefix=nil)
20
+ def initialize(response, message_prefix=nil, broker_message: nil)
10
21
  raise TypeError.new("Response has to be an integer") unless response.is_a? Integer
11
22
  @rdkafka_response = response
12
23
  @message_prefix = message_prefix
24
+ @broker_message = broker_message
13
25
  end
14
26
 
15
27
  # This error's code, for example `:partition_eof`, `:msg_size_too_large`.
@@ -57,4 +69,18 @@ module Rdkafka
57
69
  @topic_partition_list = topic_partition_list
58
70
  end
59
71
  end
72
+
73
+ # Error class for public consumer method calls on a closed consumer.
74
+ class ClosedConsumerError < BaseError
75
+ def initialize(method)
76
+ super("Illegal call to #{method.to_s} on a closed consumer")
77
+ end
78
+ end
79
+
80
+ # Error class for public producer method calls on a closed producer.
81
+ class ClosedProducerError < BaseError
82
+ def initialize(method)
83
+ super("Illegal call to #{method.to_s} on a closed producer")
84
+ end
85
+ end
60
86
  end
@@ -9,14 +9,15 @@ module Rdkafka
9
9
 
10
10
  ptr = FFI::MemoryPointer.new(:pointer)
11
11
 
12
- # Retrieve metadata flag is 0/1 for single/multiple topics.
13
- topic_flag = topic_name ? 1 : 0
12
+ # If topic_flag is 1, we request info about *all* topics in the cluster. If topic_flag is 0,
13
+ # we only request info about locally known topics (or a single topic if one is passed in).
14
+ topic_flag = topic_name.nil? ? 1 : 0
14
15
 
15
16
  # Retrieve the Metadata
16
17
  result = Rdkafka::Bindings.rd_kafka_metadata(native_client, topic_flag, native_topic, ptr, 250)
17
18
 
18
19
  # Error Handling
19
- Rdkafka::Error.new(result) unless result.zero?
20
+ raise Rdkafka::RdkafkaError.new(result) unless result.zero?
20
21
 
21
22
  metadata_from_native(ptr.read_pointer)
22
23
  ensure
@@ -34,11 +35,11 @@ module Rdkafka
34
35
 
35
36
  @topics = Array.new(metadata[:topics_count]) do |i|
36
37
  topic = TopicMetadata.new(metadata[:topics_metadata] + (i * TopicMetadata.size))
37
- Rdkafka::Error.new(topic[:rd_kafka_resp_err]) unless topic[:rd_kafka_resp_err].zero?
38
+ raise Rdkafka::RdkafkaError.new(topic[:rd_kafka_resp_err]) unless topic[:rd_kafka_resp_err].zero?
38
39
 
39
40
  partitions = Array.new(topic[:partition_count]) do |j|
40
41
  partition = PartitionMetadata.new(topic[:partitions_metadata] + (j * PartitionMetadata.size))
41
- Rdkafka::Error.new(partition[:rd_kafka_resp_err]) unless partition[:rd_kafka_resp_err].zero?
42
+ raise Rdkafka::RdkafkaError.new(partition[:rd_kafka_resp_err]) unless partition[:rd_kafka_resp_err].zero?
42
43
  partition.to_h
43
44
  end
44
45
  topic.to_h.merge!(partitions: partitions)
@@ -11,6 +11,10 @@ module Rdkafka
11
11
  def initialize(native_kafka)
12
12
  @closing = false
13
13
  @native_kafka = native_kafka
14
+
15
+ # Makes sure, that the producer gets closed before it gets GCed by Ruby
16
+ ObjectSpace.define_finalizer(self, proc { close })
17
+
14
18
  # Start thread to poll client for delivery callbacks
15
19
  @polling_thread = Thread.new do
16
20
  loop do
@@ -55,7 +59,8 @@ module Rdkafka
55
59
  # @return partition count [Integer,nil]
56
60
  #
57
61
  def partition_count(topic)
58
- Rdkafka::Metadata.new(@native_kafka, topic).topics&.select { |x| x[:topic_name] == topic }&.dig(0, :partition_count)
62
+ closed_producer_check(__method__)
63
+ Rdkafka::Metadata.new(@native_kafka, topic).topics&.first[:partition_count]
59
64
  end
60
65
 
61
66
  # 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.
@@ -74,6 +79,8 @@ module Rdkafka
74
79
  #
75
80
  # @return [DeliveryHandle] Delivery handle that can be used to wait for the result of producing this message
76
81
  def produce(topic:, payload: nil, key: nil, partition: nil, partition_key: nil, timestamp: nil, headers: nil)
82
+ closed_producer_check(__method__)
83
+
77
84
  # Start by checking and converting the input
78
85
 
79
86
  # Get payload length
@@ -117,7 +124,7 @@ module Rdkafka
117
124
  delivery_handle[:response] = -1
118
125
  delivery_handle[:partition] = -1
119
126
  delivery_handle[:offset] = -1
120
- DeliveryHandle.register(delivery_handle.to_ptr.address, delivery_handle)
127
+ DeliveryHandle.register(delivery_handle)
121
128
 
122
129
  args = [
123
130
  :int, Rdkafka::Bindings::RD_KAFKA_VTYPE_TOPIC, :string, topic,
@@ -163,5 +170,9 @@ module Rdkafka
163
170
  def call_delivery_callback(delivery_handle)
164
171
  @delivery_callback.call(delivery_handle) if @delivery_callback
165
172
  end
173
+
174
+ def closed_producer_check(method)
175
+ raise Rdkafka::ClosedProducerError.new(method) if @native_kafka.nil?
176
+ end
166
177
  end
167
178
  end
@@ -2,67 +2,21 @@ module Rdkafka
2
2
  class Producer
3
3
  # Handle to wait for a delivery report which is returned when
4
4
  # producing a message.
5
- class DeliveryHandle < FFI::Struct
5
+ class DeliveryHandle < Rdkafka::AbstractHandle
6
6
  layout :pending, :bool,
7
7
  :response, :int,
8
8
  :partition, :int,
9
9
  :offset, :int64
10
10
 
11
- REGISTRY = {}
12
-
13
- CURRENT_TIME = -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }.freeze
14
-
15
- private_constant :CURRENT_TIME
16
-
17
- def self.register(address, handle)
18
- REGISTRY[address] = handle
19
- end
20
-
21
- def self.remove(address)
22
- REGISTRY.delete(address)
23
- end
24
-
25
- # Whether the delivery handle is still pending.
26
- #
27
- # @return [Boolean]
28
- def pending?
29
- self[:pending]
11
+ # @return [String] the name of the operation (e.g. "delivery")
12
+ def operation_name
13
+ "delivery"
30
14
  end
31
15
 
32
- # Wait for the delivery report or raise an error if this takes longer than the timeout.
33
- # If there is a timeout this does not mean the message is not delivered, rdkafka might still be working on delivering the message.
34
- # In this case it is possible to call wait again.
35
- #
36
- # @param max_wait_timeout [Numeric, nil] Amount of time to wait before timing out. If this is nil it does not time out.
37
- # @param wait_timeout [Numeric] Amount of time we should wait before we recheck if there is a delivery report available
38
- #
39
- # @raise [RdkafkaError] When delivering the message failed
40
- # @raise [WaitTimeoutError] When the timeout has been reached and the handle is still pending
41
- #
42
- # @return [DeliveryReport]
43
- def wait(max_wait_timeout: 60, wait_timeout: 0.1)
44
- timeout = if max_wait_timeout
45
- CURRENT_TIME.call + max_wait_timeout
46
- else
47
- nil
48
- end
49
- loop do
50
- if pending?
51
- if timeout && timeout <= CURRENT_TIME.call
52
- raise WaitTimeoutError.new("Waiting for delivery timed out after #{max_wait_timeout} seconds")
53
- end
54
- sleep wait_timeout
55
- elsif self[:response] != 0
56
- raise RdkafkaError.new(self[:response])
57
- else
58
- return DeliveryReport.new(self[:partition], self[:offset])
59
- end
60
- end
16
+ # @return [DeliveryReport] a report on the delivery of the message
17
+ def create_result
18
+ DeliveryReport.new(self[:partition], self[:offset])
61
19
  end
62
-
63
- # Error that is raised when waiting for a delivery handle to complete
64
- # takes longer than the specified timeout.
65
- class WaitTimeoutError < RuntimeError; end
66
20
  end
67
21
  end
68
22
  end