karafka-rdkafka 0.17.1 → 0.17.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c24a6e6092e6f39f66f81e4a1ab3e07fff2afb92df937232f5237e7602d1eea9
4
- data.tar.gz: 1fcda4b35822c4c89c9a3a92ee67de8f2cb1f059f4e84f23cc12462c74bbd701
3
+ metadata.gz: 9c8adc4477dceb9b8d347a515b83cd250334fc159a862ac2315a3747fab36a3f
4
+ data.tar.gz: 25aa5b86190b3cf23ad67aae7ff5d66a5032d0bd17c80e34a776cb2af517e3cc
5
5
  SHA512:
6
- metadata.gz: dfc563c4b071bf6ee6a2595fbc98122eff9758fdfa90f297cd27541b14a39ad71ffa11290d0ddc02687c5aa6cbbdf8cf7a26594582595403f6bb05de9ef25273
7
- data.tar.gz: 8d9644f980260d159cd26624fbbbb56360a3dd3e94cebabe0eb89775143379aeef1c46e96b8b5e82daa2e7a296c97b65cba821b48eb12f6b80c3e940ddaa04d6
6
+ metadata.gz: 80c5696125626d2acd2c9cffea4e54fef6cf92269b2e8fbbff3b653bff2598bf06b4948e8fdcaff5285d245569b2c77c45958d783913ae9af79b8a816526837f
7
+ data.tar.gz: bd309b7292041e5d369a9504f85bd0f2dd61bf2dc0006dc0c9f7d58d69f367e44dbe4fce800e5f8157277c0edb316a54d5396639040fc21292f85a9c289eccad
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Rdkafka Changelog
2
2
 
3
+ ## 0.17.3 (2024-08-09)
4
+ - [Fix] Mitigate a case where FFI would not restart the background events callback dispatcher in forks.
5
+
6
+ ## 0.17.2 (2024-08-07)
7
+ - [Enhancement] Support returning `#details` for errors that do have topic/partition related extra info.
8
+
3
9
  ## 0.17.1 (2024-08-01)
4
10
  - [Enhancement] Support ability to release patches to librdkafka.
5
11
  - [Patch] Patch cooperative-sticky assignments in librdkafka.
@@ -2,7 +2,6 @@
2
2
 
3
3
  module Rdkafka
4
4
  module Callbacks
5
-
6
5
  # Extracts attributes of a rd_kafka_topic_result_t
7
6
  #
8
7
  # @private
@@ -149,13 +148,6 @@ module Rdkafka
149
148
  end
150
149
  end
151
150
 
152
- # FFI Function used for Create Topic and Delete Topic callbacks
153
- BackgroundEventCallbackFunction = FFI::Function.new(
154
- :void, [:pointer, :pointer, :pointer]
155
- ) do |client_ptr, event_ptr, opaque_ptr|
156
- BackgroundEventCallback.call(client_ptr, event_ptr, opaque_ptr)
157
- end
158
-
159
151
  # @private
160
152
  class BackgroundEventCallback
161
153
  def self.call(_, event_ptr, _)
@@ -348,13 +340,6 @@ module Rdkafka
348
340
  end
349
341
  end
350
342
 
351
- # FFI Function used for Message Delivery callbacks
352
- DeliveryCallbackFunction = FFI::Function.new(
353
- :void, [:pointer, :pointer, :pointer]
354
- ) do |client_ptr, message_ptr, opaque_ptr|
355
- DeliveryCallback.call(client_ptr, message_ptr, opaque_ptr)
356
- end
357
-
358
343
  # @private
359
344
  class DeliveryCallback
360
345
  def self.call(_, message_ptr, opaque_ptr)
@@ -387,5 +372,44 @@ module Rdkafka
387
372
  end
388
373
  end
389
374
  end
375
+
376
+ @@mutex = Mutex.new
377
+ @@current_pid = nil
378
+
379
+ class << self
380
+ # Defines or recreates after fork callbacks that require FFI thread so the callback thread
381
+ # is always correctly initialized
382
+ #
383
+ # @see https://github.com/ffi/ffi/issues/1114
384
+ def ensure_ffi_running
385
+ @@mutex.synchronize do
386
+ return if @@current_pid == ::Process.pid
387
+
388
+ if const_defined?(:BackgroundEventCallbackFunction, false)
389
+ send(:remove_const, :BackgroundEventCallbackFunction)
390
+ send(:remove_const, :DeliveryCallbackFunction)
391
+ end
392
+
393
+ # FFI Function used for Create Topic and Delete Topic callbacks
394
+ background_event_callback_function = FFI::Function.new(
395
+ :void, [:pointer, :pointer, :pointer]
396
+ ) do |client_ptr, event_ptr, opaque_ptr|
397
+ BackgroundEventCallback.call(client_ptr, event_ptr, opaque_ptr)
398
+ end
399
+
400
+ # FFI Function used for Message Delivery callbacks
401
+ delivery_callback_function = FFI::Function.new(
402
+ :void, [:pointer, :pointer, :pointer]
403
+ ) do |client_ptr, message_ptr, opaque_ptr|
404
+ DeliveryCallback.call(client_ptr, message_ptr, opaque_ptr)
405
+ end
406
+
407
+ const_set(:BackgroundEventCallbackFunction, background_event_callback_function)
408
+ const_set(:DeliveryCallbackFunction, delivery_callback_function)
409
+
410
+ @@current_pid = ::Process.pid
411
+ end
412
+ end
413
+ end
390
414
  end
391
415
  end
@@ -146,6 +146,8 @@ module Rdkafka
146
146
  #
147
147
  # @return [Config]
148
148
  def initialize(config_hash = {})
149
+ Callbacks.ensure_ffi_running
150
+
149
151
  @config_hash = DEFAULT_CONFIG.merge(config_hash)
150
152
  @consumer_rebalance_listener = nil
151
153
  @consumer_poll_set = true
data/lib/rdkafka/error.rb CHANGED
@@ -6,6 +6,9 @@ module Rdkafka
6
6
 
7
7
  # Error returned by the underlying rdkafka library.
8
8
  class RdkafkaError < BaseError
9
+ # Empty hash for details default allocation
10
+ EMPTY_HASH = {}.freeze
11
+
9
12
  # The underlying raw error response
10
13
  # @return [Integer]
11
14
  attr_reader :rdkafka_response
@@ -18,6 +21,10 @@ module Rdkafka
18
21
  # @return [String]
19
22
  attr_reader :broker_message
20
23
 
24
+ # Optional details hash specific to a given error or empty hash if none or not supported
25
+ # @return [Hash]
26
+ attr_reader :details
27
+
21
28
  class << self
22
29
  def build_from_c(response_ptr, message_prefix = nil, broker_message: nil)
23
30
  code = Rdkafka::Bindings.rd_kafka_error_code(response_ptr)
@@ -54,7 +61,21 @@ module Rdkafka
54
61
  message_prefix ||= response_ptr_or_code[:payload].read_string(response_ptr_or_code[:len])
55
62
  end
56
63
 
57
- new(response_ptr_or_code[:err], message_prefix, broker_message: broker_message)
64
+ details = if response_ptr_or_code[:rkt].null?
65
+ EMPTY_HASH
66
+ else
67
+ {
68
+ partition: response_ptr_or_code[:partition],
69
+ offset: response_ptr_or_code[:offset],
70
+ topic: Bindings.rd_kafka_topic_name(response_ptr_or_code[:rkt])
71
+ }.freeze
72
+ end
73
+ new(
74
+ response_ptr_or_code[:err],
75
+ message_prefix,
76
+ broker_message: broker_message,
77
+ details: details
78
+ )
58
79
  else
59
80
  build_from_c(response_ptr_or_code, message_prefix)
60
81
  end
@@ -73,7 +94,8 @@ module Rdkafka
73
94
  broker_message: nil,
74
95
  fatal: false,
75
96
  retryable: false,
76
- abortable: false
97
+ abortable: false,
98
+ details: EMPTY_HASH
77
99
  )
78
100
  raise TypeError.new("Response has to be an integer") unless response.is_a? Integer
79
101
  @rdkafka_response = response
@@ -82,6 +104,7 @@ module Rdkafka
82
104
  @fatal = fatal
83
105
  @retryable = retryable
84
106
  @abortable = abortable
107
+ @details = details
85
108
  end
86
109
 
87
110
  # This error's code, for example `:partition_eof`, `:msg_size_too_large`.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rdkafka
4
- VERSION = "0.17.1"
4
+ VERSION = "0.17.3"
5
5
  LIBRDKAFKA_VERSION = "2.5.0"
6
6
  LIBRDKAFKA_SOURCE_SHA256 = "3dc62de731fd516dfb1032861d9a580d4d0b5b0856beb0f185d06df8e6c26259"
7
7
  end
@@ -737,4 +737,18 @@ describe Rdkafka::Admin do
737
737
  end
738
738
  end
739
739
  end
740
+
741
+ context "when operating from a fork" do
742
+ # @see https://github.com/ffi/ffi/issues/1114
743
+ it 'expect to be able to create topics and run other admin operations without hanging' do
744
+ # If the FFI issue is not mitigated, this will hang forever
745
+ pid = fork do
746
+ admin
747
+ .create_topic(topic_name, topic_partition_count, topic_replication_factor)
748
+ .wait
749
+ end
750
+
751
+ Process.wait(pid)
752
+ end
753
+ end
740
754
  end
@@ -1467,4 +1467,39 @@ describe Rdkafka::Consumer do
1467
1467
  end
1468
1468
  end
1469
1469
  end
1470
+
1471
+ describe "when reaching eof on a topic and eof reporting enabled" do
1472
+ let(:consumer) { rdkafka_consumer_config(:"enable.partition.eof" => true).consumer }
1473
+
1474
+ it "should return proper details" do
1475
+ (0..2).each do |i|
1476
+ producer.produce(
1477
+ topic: "consume_test_topic",
1478
+ key: "key lag #{i}",
1479
+ partition: i
1480
+ ).wait
1481
+ end
1482
+
1483
+ # Consume to the end
1484
+ consumer.subscribe("consume_test_topic")
1485
+ eof_count = 0
1486
+ eof_error = nil
1487
+
1488
+ loop do
1489
+ begin
1490
+ consumer.poll(100)
1491
+ rescue Rdkafka::RdkafkaError => error
1492
+ if error.is_partition_eof?
1493
+ eof_error = error
1494
+ end
1495
+ break if eof_error
1496
+ end
1497
+ end
1498
+
1499
+ expect(eof_error.code).to eq(:partition_eof)
1500
+ expect(eof_error.details[:topic]).to eq('consume_test_topic')
1501
+ expect(eof_error.details[:partition]).to be_a(Integer)
1502
+ expect(eof_error.details[:offset]).to be_a(Integer)
1503
+ end
1504
+ end
1470
1505
  end
@@ -11,6 +11,12 @@ describe Rdkafka::RdkafkaError do
11
11
  expect(Rdkafka::RdkafkaError.new(10, "message prefix").message_prefix).to eq "message prefix"
12
12
  end
13
13
 
14
+ it "should have empty frozen details by default" do
15
+ error = Rdkafka::RdkafkaError.new(10, "message prefix")
16
+ expect(error.details).to eq({})
17
+ expect(error.details).to be_frozen
18
+ end
19
+
14
20
  it "should create an error with a broker message" do
15
21
  expect(Rdkafka::RdkafkaError.new(10, broker_message: "broker message").broker_message).to eq "broker message"
16
22
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka-rdkafka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.1
4
+ version: 0.17.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thijs Cadier
@@ -36,7 +36,7 @@ cert_chain:
36
36
  AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
37
37
  msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
38
38
  -----END CERTIFICATE-----
39
- date: 2024-08-01 00:00:00.000000000 Z
39
+ date: 2024-08-09 00:00:00.000000000 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: ffi
metadata.gz.sig CHANGED
Binary file