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 +4 -4
- data/CHANGELOG.md +1 -0
- data/ext/librdkafka.so +0 -0
- data/lib/rdkafka/bindings.rb +9 -0
- data/lib/rdkafka/consumer.rb +57 -0
- data/lib/rdkafka/helpers/time.rb +5 -0
- data/lib/rdkafka/producer/partitions_count_cache.rb +6 -6
- data/lib/rdkafka/producer.rb +39 -0
- data/lib/rdkafka/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0fc37d005a8920103966e128744f2afefb21867046b43777d31cb5c40bc995f1
|
|
4
|
+
data.tar.gz: 44a57e87fb413e25815419909cdb2de0f138e4c6cd83e10ef3ee0495bb324f4c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/rdkafka/bindings.rb
CHANGED
|
@@ -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
|
data/lib/rdkafka/consumer.rb
CHANGED
|
@@ -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
|
#
|
data/lib/rdkafka/helpers/time.rb
CHANGED
|
@@ -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] = [
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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 [
|
|
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
|
-
|
|
222
|
+
monotonic_now_ms - timestamp > @ttl_ms
|
|
223
223
|
end
|
|
224
224
|
end
|
|
225
225
|
end
|
data/lib/rdkafka/producer.rb
CHANGED
|
@@ -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.
|
data/lib/rdkafka/version.rb
CHANGED