Class: LittleGhost::Execution
- Inherits:
-
Object
- Object
- LittleGhost::Execution
- Defined in:
- lib/little_ghost/execution.rb
Overview
Runs one dormant Run in a supervised worker while the caller remains free to serve health checks, deliver interruptions, or coordinate process shutdown.
execution = agent.start_execution(message: "Investigate transfer 481") do |event|
event_buffer << event
end
execution.interrupt_response(message: "Include the latest ledger entry")
execution.wait(deadline: Time.now + 30)
execution.run.completed? # => true
An execution owns its worker. The worker receives a snapshot of the caller's
request-scoped ExecutionState. The Run continues to own its workspace,
sandbox, session, entrypoint, and registered resources. close requests
cooperative cancellation and waits for both the worker and in-flight
interruption calls.
Instance Attribute Summary collapse
-
#run ⇒ Object
readonly
The supervised Run and an exception raised outside the Run's ordinary terminal outcome, such as event delivery or cleanup failure.
Class Method Summary collapse
-
.start(run, &event_consumer) ⇒ Object
Starts
runimmediately and returns its supervising Execution.
Instance Method Summary collapse
-
#active? ⇒ Boolean
Indicates that the worker or an interruption call is still active.
-
#cancel ⇒ Object
Requests cooperative cancellation and returns
self. -
#close(deadline: nil) ⇒ Object
Prevents new interruptions, requests cancellation, and waits for shutdown.
-
#error ⇒ Object
Returns an event-delivery or cleanup exception raised by the worker.
-
#finished? ⇒ Boolean
Indicates that the worker and all interruption calls have finished.
-
#initialize(run, event_consumer: nil) ⇒ Execution
constructor
:nodoc:.
-
#interrupt_response(payload = nil, **options) ⇒ Object
Prepares and delivers one interruption to the active run.
-
#state ⇒ Object
Returns
:pending,:running, or:finished. -
#wait(deadline: nil) ⇒ Object
Waits for the worker and in-flight interruptions, then returns the Run.
Constructor Details
#initialize(run, event_consumer: nil) ⇒ Execution
:nodoc:
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/little_ghost/execution.rb', line 36 def initialize(run, event_consumer: nil) # :nodoc: raise ArgumentError, "run must be a LittleGhost::Run" unless run.is_a?(Run) unless event_consumer.nil? || event_consumer.respond_to?(:call) raise ArgumentError, "event consumer must be callable" end @run = run @event_consumer = event_consumer @state = :pending @error = nil @mutex = Mutex.new @condition = ConditionVariable.new @active_interruptions = 0 @closing = false @execution_state = ExecutionState.capture end |
Instance Attribute Details
#run ⇒ Object (readonly)
The supervised Run and an exception raised outside the Run's ordinary terminal outcome, such as event delivery or cleanup failure.
23 24 25 |
# File 'lib/little_ghost/execution.rb', line 23 def run @run end |
Class Method Details
.start(run, &event_consumer) ⇒ Object
Starts run immediately and returns its supervising Execution.
The optional block receives each StreamEvent on the worker thread. It must be safe to call from that thread and should not retain sensitive event content longer than the application requires.
31 32 33 |
# File 'lib/little_ghost/execution.rb', line 31 def start(run, &event_consumer) new(run, event_consumer:).send(:start) end |
Instance Method Details
#active? ⇒ Boolean
Indicates that the worker or an interruption call is still active.
64 65 66 |
# File 'lib/little_ghost/execution.rb', line 64 def active? @mutex.synchronize { @state != :finished || @active_interruptions.positive? } end |
#cancel ⇒ Object
Requests cooperative cancellation and returns self.
96 97 98 99 |
# File 'lib/little_ghost/execution.rb', line 96 def cancel run.cancellation_token.cancel self end |
#close(deadline: nil) ⇒ Object
Prevents new interruptions, requests cancellation, and waits for shutdown.
The operation is idempotent. deadline has the same meaning as in #wait.
117 118 119 120 121 |
# File 'lib/little_ghost/execution.rb', line 117 def close(deadline: nil) @mutex.synchronize { @closing = true } cancel wait(deadline:) end |
#error ⇒ Object
Returns an event-delivery or cleanup exception raised by the worker.
59 60 61 |
# File 'lib/little_ghost/execution.rb', line 59 def error @mutex.synchronize { @error } end |
#finished? ⇒ Boolean
Indicates that the worker and all interruption calls have finished.
69 70 71 |
# File 'lib/little_ghost/execution.rb', line 69 def finished? !active? end |
#interrupt_response(payload = nil, **options) ⇒ Object
Prepares and delivers one interruption to the active run.
payload may be a message or a Hash containing message and the options
accepted by Run#interrupt_response. Runtime hooks receive the Hash before
delivery, allowing them to materialize trusted application attachments.
Calls may overlap, but close prevents new calls and waits for calls that
have already begun.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/little_ghost/execution.rb', line 80 def interrupt_response(payload = nil, **) if payload.nil? && .key?(:message) payload = .delete(:message) end interruption_started = false begin_interruption! interruption_started = true run.interrupt_response_with do prepared = run.prepare_interruption(interruption_payload(payload, )) interruption_arguments(prepared, ) end ensure finish_interruption! if interruption_started end |
#state ⇒ Object
Returns :pending, :running, or :finished.
54 55 56 |
# File 'lib/little_ghost/execution.rb', line 54 def state @mutex.synchronize { @state } end |
#wait(deadline: nil) ⇒ Object
Waits for the worker and in-flight interruptions, then returns the Run.
deadline is an absolute Time. Reaching it raises DeadlineExceededError
without cancelling the run. An event-delivery or cleanup failure raised by
the worker is re-raised after all supervised work finishes.
106 107 108 109 110 111 112 113 |
# File 'lib/little_ghost/execution.rb', line 106 def wait(deadline: nil) worker = wait_until_finished(deadline:) worker.join caught = error raise caught if caught run end |