Class: Phronomy::CancellationToken
- Inherits:
-
Object
- Object
- Phronomy::CancellationToken
- Defined in:
- lib/phronomy/cancellation_token.rb
Overview
Provides cooperative cancellation for agent invocations.
Pass a token to an agent via +config: { cancellation_token: token }+. The agent checks the token before each LLM call and raises CancellationError when the token is cancelled or the optional deadline has passed.
A token may be shared across multiple agent invocations and across threads; all access to internal state is protected by a Mutex.
Instance Attribute Summary collapse
-
#deadline ⇒ Time?
readonly
The wall-clock deadline passed to #initialize, or +nil+.
Class Method Summary collapse
-
.timeout_after(seconds) ⇒ CancellationToken
Returns a new token that will expire after +seconds+ seconds, measured with the monotonic clock (+Process::CLOCK_MONOTONIC+).
Instance Method Summary collapse
-
#cancel! ⇒ self
Mark the token as cancelled and fire any registered #on_cancel callbacks.
-
#cancelled? ⇒ Boolean
Returns +true+ when the token has been explicitly cancelled via #cancel!, when the wall-clock deadline has passed, or when the monotonic deadline (set by CancellationToken.timeout_after) has elapsed.
-
#initialize(deadline: nil, monotonic_deadline: nil) ⇒ CancellationToken
constructor
A new instance of CancellationToken.
-
#on_cancel { ... } ⇒ self
Registers a one-shot callback invoked when this token is explicitly cancelled via #cancel!.
-
#raise_if_cancelled!(message = "invocation cancelled") ⇒ nil
Raises CancellationError if the token is cancelled.
-
#remaining_monotonic_seconds ⇒ Float?
Returns the remaining seconds until the monotonic deadline fires, or +nil+ when no monotonic deadline is set.
Constructor Details
#initialize(deadline: nil, monotonic_deadline: nil) ⇒ CancellationToken
Returns a new instance of CancellationToken.
50 51 52 53 54 55 56 |
# File 'lib/phronomy/cancellation_token.rb', line 50 def initialize(deadline: nil, monotonic_deadline: nil) @cancelled = false @deadline = deadline @monotonic_deadline = monotonic_deadline @mutex = Mutex.new @cancel_callbacks = [] end |
Instance Attribute Details
#deadline ⇒ Time? (readonly)
Returns the wall-clock deadline passed to #initialize, or +nil+.
59 60 61 |
# File 'lib/phronomy/cancellation_token.rb', line 59 def deadline @deadline end |
Class Method Details
.timeout_after(seconds) ⇒ CancellationToken
Returns a new token that will expire after +seconds+ seconds, measured with the monotonic clock (+Process::CLOCK_MONOTONIC+). Unlike constructing a token with +deadline: Time.now + seconds+, this factory is immune to NTP adjustments and DST transitions.
39 40 41 42 |
# File 'lib/phronomy/cancellation_token.rb', line 39 def self.timeout_after(seconds) monotonic_deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds new(monotonic_deadline: monotonic_deadline) end |
Instance Method Details
#cancel! ⇒ self
Mark the token as cancelled and fire any registered #on_cancel callbacks. Thread-safe; idempotent — calling multiple times has no additional effect.
99 100 101 102 103 104 105 106 107 |
# File 'lib/phronomy/cancellation_token.rb', line 99 def cancel! callbacks = @mutex.synchronize do return self if @cancelled @cancelled = true @cancel_callbacks.dup end callbacks.each(&:call) self end |
#cancelled? ⇒ Boolean
Returns +true+ when the token has been explicitly cancelled via #cancel!, when the wall-clock deadline has passed, or when the monotonic deadline (set by timeout_after) has elapsed. Thread-safe.
114 115 116 117 118 119 |
# File 'lib/phronomy/cancellation_token.rb', line 114 def cancelled? return true if @mutex.synchronize { @cancelled } return true if !@deadline.nil? && Time.now >= @deadline !@monotonic_deadline.nil? && Process.clock_gettime(Process::CLOCK_MONOTONIC) >= @monotonic_deadline end |
#on_cancel { ... } ⇒ self
Registers a one-shot callback invoked when this token is explicitly cancelled via #cancel!. If the token is already cancelled, the block is called immediately (still within the caller's thread).
Callbacks are NOT fired for deadline-based cancellation (i.e. when #cancelled? returns +true+ due to +@monotonic_deadline+ expiry). Use Runtime#timer_queue to schedule deadline callbacks.
82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/phronomy/cancellation_token.rb', line 82 def on_cancel(&block) already_cancelled = @mutex.synchronize do if @cancelled true else @cancel_callbacks << block false end end block.call if already_cancelled self end |
#raise_if_cancelled!(message = "invocation cancelled") ⇒ nil
Raises Phronomy::CancellationError if the token is cancelled. A convenience method for cooperative cancellation checks inside tools, RAG loaders, and hooks, replacing the +if cancelled? then raise+ pattern.
129 130 131 |
# File 'lib/phronomy/cancellation_token.rb', line 129 def raise_if_cancelled!( = "invocation cancelled") raise Phronomy::CancellationError, if cancelled? end |
#remaining_monotonic_seconds ⇒ Float?
Returns the remaining seconds until the monotonic deadline fires, or +nil+ when no monotonic deadline is set. Returns 0.0 if already past.
65 66 67 68 69 |
# File 'lib/phronomy/cancellation_token.rb', line 65 def remaining_monotonic_seconds return nil if @monotonic_deadline.nil? remaining = @monotonic_deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) [remaining, 0.0].max end |