Class: Phronomy::CancellationToken

Inherits:
Object
  • Object
show all
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.

Examples:

Explicit cancel from another thread

token = Phronomy::CancellationToken.new
Thread.new { sleep 5; token.cancel! }
result = agent.invoke("...", config: { cancellation_token: token })

Hard deadline via monotonic clock (recommended)

token = Phronomy::CancellationToken.timeout_after(30)
result = agent.invoke("...", config: { cancellation_token: token })

Hard deadline via wall-clock (legacy)

token = Phronomy::CancellationToken.new(deadline: Time.now + 30)
result = agent.invoke("...", config: { cancellation_token: token })

Propagate to parallel workers

token = Phronomy::CancellationToken.new
orchestrator.dispatch_parallel(task1, task2, cancellation_token: token)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(deadline: nil, monotonic_deadline: nil) ⇒ CancellationToken

Returns a new instance of CancellationToken.

Parameters:

  • deadline (Time, nil) (defaults to: nil)

    optional wall-clock deadline; the token reports +cancelled?+ as +true+ once +Time.now >= deadline+. Prefer timeout_after for duration-based cancellation.

  • monotonic_deadline (Float, nil) (defaults to: nil)

    internal monotonic timestamp set by timeout_after; prefer that factory method over passing this directly.



50
51
52
53
54
55
# 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
end

Instance Attribute Details

#deadlineTime? (readonly)

Returns the wall-clock deadline passed to #initialize, or +nil+.

Returns:

  • (Time, nil)

    the wall-clock deadline passed to #initialize, or +nil+.



58
59
60
# File 'lib/phronomy/cancellation_token.rb', line 58

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.

Parameters:

  • seconds (Numeric)

    duration in seconds until the token expires.

Returns:



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. Thread-safe; may be called from any thread.

Returns:

  • (self)


63
64
65
66
# File 'lib/phronomy/cancellation_token.rb', line 63

def cancel!
  @mutex.synchronize { @cancelled = true }
  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.

Returns:

  • (Boolean)


73
74
75
76
77
78
# File 'lib/phronomy/cancellation_token.rb', line 73

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

#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.

Parameters:

  • message (String) (defaults to: "invocation cancelled")

    optional error message

Returns:

  • (nil)

    when the token is not cancelled

Raises:



88
89
90
# File 'lib/phronomy/cancellation_token.rb', line 88

def raise_if_cancelled!(message = "invocation cancelled")
  raise Phronomy::CancellationError, message if cancelled?
end