33require "ffi"
44
55module Rdkafka
6+ # This class serves as an abstract base class to represent handles within the Rdkafka module.
7+ # As a subclass of `FFI::Struct`, this class provides a blueprint for other specific handle
8+ # classes to inherit from, ensuring they adhere to a particular structure and behavior.
9+ #
10+ # Subclasses must define their own layout, and the layout must start with:
11+ #
12+ # layout :pending, :bool,
13+ # :response, :int
614 class AbstractHandle < FFI ::Struct
7- # Subclasses must define their own layout, and the layout must start with:
8- #
9- # layout :pending, :bool,
10- # :response, :int
15+ include Helpers ::Time
1116
17+ # Registry for registering all the handles.
1218 REGISTRY = { }
1319
14- CURRENT_TIME = -> { Process . clock_gettime ( Process ::CLOCK_MONOTONIC ) } . freeze
15-
16- private_constant :CURRENT_TIME
20+ class << self
21+ # Adds handle to the register
22+ #
23+ # @param handle [AbstractHandle] any handle we want to register
24+ def register ( handle )
25+ address = handle . to_ptr . address
26+ REGISTRY [ address ] = handle
27+ end
1728
18- def self . register ( handle )
19- address = handle . to_ptr . address
20- REGISTRY [ address ] = handle
29+ # Removes handle from the register based on the handle address
30+ #
31+ # @param address [Integer] address of the registered handle we want to remove
32+ def remove ( address )
33+ REGISTRY . delete ( address )
34+ end
2135 end
2236
23- def self . remove ( address )
24- REGISTRY . delete ( address )
25- end
2637
2738 # Whether the handle is still pending.
2839 #
@@ -32,26 +43,30 @@ def pending?
3243 end
3344
3445 # Wait for the operation to complete or raise an error if this takes longer than the timeout.
35- # If there is a timeout this does not mean the operation failed, rdkafka might still be working on the operation.
36- # In this case it is possible to call wait again.
46+ # If there is a timeout this does not mean the operation failed, rdkafka might still be working
47+ # on the operation. In this case it is possible to call wait again.
3748 #
38- # @param max_wait_timeout [Numeric, nil] Amount of time to wait before timing out. If this is nil it does not time out.
39- # @param wait_timeout [Numeric] Amount of time we should wait before we recheck if the operation has completed
49+ # @param max_wait_timeout [Numeric, nil] Amount of time to wait before timing out.
50+ # If this is nil it does not time out.
51+ # @param wait_timeout [Numeric] Amount of time we should wait before we recheck if the
52+ # operation has completed
53+ #
54+ # @return [Object] Operation-specific result
4055 #
4156 # @raise [RdkafkaError] When the operation failed
4257 # @raise [WaitTimeoutError] When the timeout has been reached and the handle is still pending
43- #
44- # @return [Object] Operation-specific result
4558 def wait ( max_wait_timeout : 60 , wait_timeout : 0.1 )
4659 timeout = if max_wait_timeout
47- CURRENT_TIME . call + max_wait_timeout
60+ monotonic_now + max_wait_timeout
4861 else
4962 nil
5063 end
5164 loop do
5265 if pending?
53- if timeout && timeout <= CURRENT_TIME . call
54- raise WaitTimeoutError . new ( "Waiting for #{ operation_name } timed out after #{ max_wait_timeout } seconds" )
66+ if timeout && timeout <= monotonic_now
67+ raise WaitTimeoutError . new (
68+ "Waiting for #{ operation_name } timed out after #{ max_wait_timeout } seconds"
69+ )
5570 end
5671 sleep wait_timeout
5772 elsif self [ :response ] != 0
0 commit comments