karafka-rdkafka 0.24.0.rc2-aarch64-linux-gnu → 0.24.0.rc3-aarch64-linux-gnu

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5a0a12c81986370bd3e74f1d50e072a1efaec78f87b9920ffe0c7a9633192c5
4
- data.tar.gz: 3c1ff95662b2ba5bb6912ebeda520209f7c6b818762b3fb5f243a4751f0b2b10
3
+ metadata.gz: 0fc37d005a8920103966e128744f2afefb21867046b43777d31cb5c40bc995f1
4
+ data.tar.gz: 44a57e87fb413e25815419909cdb2de0f138e4c6cd83e10ef3ee0495bb324f4c
5
5
  SHA512:
6
- metadata.gz: c72c872626ef1d51b63f585a65a472d7d7b94fb050a610be91f409b686c010f64167d9bca633edbf2862ebb40c413156f9ae422045e103e2537e85e8bbb2cafd
7
- data.tar.gz: f45068691155efba1f50b5f7b0794f2d23a2ae4e7f8db9651af2f5bed98e18c053a8c79e21ccbf19d6dfa434689740718e4e9e3b187b84a0d269fe17e822411a
6
+ metadata.gz: 52b918e97d0db2b47bcdc8adbe73c24df0a82fb0cf3854cff644735de31cc577b509c8fd10d19a29087e6a419feacf930cb73f680f081deeb612933e3e402d46
7
+ data.tar.gz: bc22e5d641c2e3bdac08844e6899e7ba750ddb4b3c1a7345175b2678f24f9a31fe088ef04799968c091520311398e616ce2377856ad90887d628bbdf3c825e9b
data/CHANGELOG.md CHANGED
@@ -15,6 +15,7 @@
15
15
  - [Enhancement] Use native ARM64 runners instead of QEMU emulation for Alpine musl aarch64 builds, improving build performance and reliability (from upstream).
16
16
  - [Enhancement] Enable parallel compilation (`make -j$(nproc)`) for ARM64 Alpine musl builds (from upstream).
17
17
  - [Enhancement] Bump librdkafka to 2.13.0.
18
+ - [Enhancement] Add non-blocking poll methods (`poll_nb`, `events_poll_nb`) that skip GVL release for efficient fiber scheduler integration when using `poll(0)` (from upstream).
18
19
  - [Fix] Fix Kerberos build on Alpine 3.23+ (GCC 15/C23) by forcing C17 semantics to maintain compatibility with old-style K&R declarations in MIT Kerberos and Cyrus SASL dependencies.
19
20
 
20
21
  ## 0.23.1 (2025-11-14)
data/ext/librdkafka.so CHANGED
Binary file
@@ -96,6 +96,12 @@ module Rdkafka
96
96
  attach_function :rd_kafka_poll, [:pointer, :int], :int, blocking: true
97
97
  attach_function :rd_kafka_outq_len, [:pointer], :int, blocking: true
98
98
 
99
+ # Non-blocking poll variants (do not release GVL)
100
+ # These are more efficient for poll(0) calls in fiber schedulers where GVL
101
+ # release/reacquire overhead is wasteful since we don't expect to wait.
102
+ # Uses the same underlying C function but with blocking: false to skip GVL release.
103
+ attach_function :rd_kafka_poll_nb, :rd_kafka_poll, [:pointer, :int], :int, blocking: false
104
+
99
105
  # Metadata
100
106
 
101
107
  attach_function :rd_kafka_name, [:pointer], :string
@@ -398,6 +404,9 @@ module Rdkafka
398
404
  attach_function :rd_kafka_commit, [:pointer, :pointer, :bool], :int, blocking: true
399
405
  attach_function :rd_kafka_poll_set_consumer, [:pointer], :void, blocking: true
400
406
  attach_function :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: true
407
+ # Non-blocking consumer poll variant (does not release GVL)
408
+ # More efficient for poll(0) calls in fiber schedulers.
409
+ attach_function :rd_kafka_consumer_poll_nb, :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: false
401
410
  attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
402
411
  attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
403
412
  attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
@@ -606,6 +606,47 @@ module Rdkafka
606
606
  end
607
607
  end
608
608
 
609
+ # Poll for the next message without releasing the GVL (Global VM Lock).
610
+ #
611
+ # This is more efficient than regular polling for non-blocking poll(0) calls,
612
+ # particularly useful in fiber scheduler contexts where GVL release/reacquire
613
+ # overhead is wasteful since we don't expect to wait.
614
+ #
615
+ # @param timeout_ms [Integer] Timeout of this poll (default: 0 for non-blocking)
616
+ # @return [Message, nil] A message or nil if there was no new message within the timeout
617
+ # @raise [RdkafkaError] When polling fails
618
+ #
619
+ # @example Using with fiber scheduler
620
+ # # After receiving IO notification that messages are available
621
+ # while msg = consumer.poll_nb
622
+ # process(msg)
623
+ # end
624
+ def poll_nb(timeout_ms = 0)
625
+ closed_consumer_check(__method__)
626
+
627
+ message_ptr = @native_kafka.with_inner do |inner|
628
+ Rdkafka::Bindings.rd_kafka_consumer_poll_nb(inner, timeout_ms)
629
+ end
630
+
631
+ if message_ptr.null?
632
+ nil
633
+ else
634
+ # Create struct wrapper
635
+ native_message = Rdkafka::Bindings::Message.new(message_ptr)
636
+ # Raise error if needed
637
+ if native_message[:err] != Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
638
+ raise Rdkafka::RdkafkaError.new(native_message[:err])
639
+ end
640
+ # Create a message to pass out
641
+ Rdkafka::Consumer::Message.new(native_message)
642
+ end
643
+ ensure
644
+ # Clean up rdkafka message if there is one
645
+ if message_ptr && !message_ptr.null?
646
+ Rdkafka::Bindings.rd_kafka_message_destroy(message_ptr)
647
+ end
648
+ end
649
+
609
650
  # Polls the main rdkafka queue (not the consumer one). Do **NOT** use it if `consumer_poll_set`
610
651
  # was set to `true`.
611
652
  #
@@ -632,6 +673,22 @@ module Rdkafka
632
673
  end
633
674
  end
634
675
 
676
+ # Polls the main rdkafka queue without releasing the GVL (Global VM Lock).
677
+ #
678
+ # This is more efficient than regular events_poll for non-blocking poll(0) calls,
679
+ # particularly useful in fiber scheduler contexts where GVL release/reacquire
680
+ # overhead is wasteful since we don't expect to wait.
681
+ #
682
+ # @param timeout_ms [Integer] poll timeout (default: 0 for non-blocking)
683
+ # @return [Integer] the number of events served
684
+ #
685
+ # @see #events_poll for more details on when to use this method
686
+ def events_poll_nb(timeout_ms = 0)
687
+ @native_kafka.with_inner do |inner|
688
+ Rdkafka::Bindings.rd_kafka_poll_nb(inner, timeout_ms)
689
+ end
690
+ end
691
+
635
692
  # Poll for new messages and yield for each received one. Iteration
636
693
  # will end when the consumer is closed.
637
694
  #
@@ -9,6 +9,11 @@ module Rdkafka
9
9
  def monotonic_now
10
10
  ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
11
11
  end
12
+
13
+ # @return [Integer] current monotonic time in milliseconds
14
+ def monotonic_now_ms
15
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :millisecond)
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -147,17 +147,17 @@ module Rdkafka
147
147
 
148
148
  if current_info.nil?
149
149
  # Create new entry
150
- @counts[topic] = [monotonic_now, new_count]
150
+ @counts[topic] = [monotonic_now_ms, new_count]
151
151
  else
152
152
  current_count = current_info[1]
153
153
 
154
154
  if new_count > current_count
155
155
  # Update to higher count value
156
- current_info[0] = monotonic_now
156
+ current_info[0] = monotonic_now_ms
157
157
  current_info[1] = new_count
158
158
  else
159
159
  # Same or lower count, update timestamp only
160
- current_info[0] = monotonic_now
160
+ current_info[0] = monotonic_now_ms
161
161
  end
162
162
  end
163
163
  end
@@ -211,15 +211,15 @@ module Rdkafka
211
211
  return unless current_info
212
212
 
213
213
  # Update the timestamp in-place
214
- current_info[0] = monotonic_now
214
+ current_info[0] = monotonic_now_ms
215
215
  end
216
216
 
217
217
  # Check if a timestamp has expired based on the TTL
218
218
  #
219
- # @param timestamp [Float] Monotonic timestamp to check
219
+ # @param timestamp [Integer] Monotonic timestamp in milliseconds to check
220
220
  # @return [Boolean] true if expired, false otherwise
221
221
  def expired?(timestamp)
222
- (monotonic_now - timestamp) * 1_000 > @ttl_ms
222
+ monotonic_now_ms - timestamp > @ttl_ms
223
223
  end
224
224
  end
225
225
  end
@@ -338,6 +338,45 @@ module Rdkafka
338
338
 
339
339
  alias_method :queue_length, :queue_size
340
340
 
341
+ # Drains the producer's event queue by continuously polling until empty or time limit reached.
342
+ #
343
+ # This method is useful when you need to ensure delivery callbacks are processed within a
344
+ # bounded time, particularly when polling multiple producers from a single thread where
345
+ # fair scheduling is required to prevent starvation.
346
+ #
347
+ # Uses non-blocking polls internally (no GVL release) for efficiency. The method holds
348
+ # a single `with_inner` lock for the duration, minimizing per-poll overhead when processing
349
+ # many events.
350
+ #
351
+ # @param timeout_ms [Integer] maximum time to spend draining in milliseconds (default: 100)
352
+ # @return [Boolean] true if no more events to process, false if stopped due to time limit
353
+ # @raise [Rdkafka::ClosedProducerError] if called on a closed producer
354
+ #
355
+ # @note This method holds the inner lock for up to `timeout_ms`. Other producer operations
356
+ # (produce, close, etc.) will wait until this method returns.
357
+ # @note This method is thread-safe as it uses @native_kafka.with_inner synchronization
358
+ #
359
+ # @example Basic usage - drain for up to 100ms
360
+ # fully_drained = producer.poll_drain_nb
361
+ #
362
+ # @example Round-robin polling multiple producers fairly
363
+ # producers.each do |producer|
364
+ # fully_drained = producer.poll_drain_nb(10)
365
+ # # If false, this producer has more pending events
366
+ # end
367
+ def poll_drain_nb(timeout_ms = 100)
368
+ closed_producer_check(__method__)
369
+
370
+ @native_kafka.with_inner do |inner|
371
+ deadline = monotonic_now_ms + timeout_ms
372
+
373
+ loop do
374
+ break true if Rdkafka::Bindings.rd_kafka_poll_nb(inner, 0).zero?
375
+ break false if monotonic_now_ms >= deadline
376
+ end
377
+ end
378
+ end
379
+
341
380
  # Partition count for a given topic.
342
381
  #
343
382
  # @param topic [String] The topic name.
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rdkafka
4
4
  # Current rdkafka-ruby gem version
5
- VERSION = "0.24.0.rc2"
5
+ VERSION = "0.24.0.rc3"
6
6
  # Target librdkafka version to be used
7
7
  LIBRDKAFKA_VERSION = "2.13.0"
8
8
  # SHA256 hash of the librdkafka source tarball for verification
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.24.0.rc2
4
+ version: 0.24.0.rc3
5
5
  platform: aarch64-linux-gnu
6
6
  authors:
7
7
  - Thijs Cadier