Class: LittleGhost::Execution
- Inherits:
-
Object
- Object
- LittleGhost::Execution
- Defined in:
- lib/little_ghost/execution.rb
Overview
Runs one dormant Run in the background while the caller remains free to serve health checks, deliver interjections, or coordinate shutdown.
execution = agent.start_execution(message: "Investigate transfer 481") do |event|
event_buffer << event
end
execution.interject(message: "Include the latest ledger entry")
execution.wait(deadline: Time.now + 30)
execution.run.completed? # => true
The Runtime selects a scheduled fiber or worker thread for the execution.
LittleGhost copies the caller's ExecutionState, but not other application
fiber-local or thread-local values. The Run continues to own its workspace,
sandbox, session, entrypoint, and registered resources. close requests
cooperative cancellation and waits for the execution and any in-flight
interjection calls.
Instance Attribute Summary collapse
-
#run ⇒ Object
readonly
The supervised Run.
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 Execution or an interjection call is still active.
-
#cancel ⇒ Object
Requests cooperative cancellation and returns
self. -
#close(deadline: nil) ⇒ Object
Prevents new interjections, requests cancellation, and waits for shutdown.
-
#error ⇒ Object
Returns an event-delivery or cleanup exception raised by the Execution.
-
#finished? ⇒ Boolean
Indicates that the Execution and all interjection calls have finished.
-
#initialize(run, event_consumer: nil) ⇒ Execution
constructor
:nodoc:.
-
#interject(payload = nil, **options) ⇒ Object
Prepares and delivers one interjection to the active run.
-
#state ⇒ Object
Returns
:pending,:running, or:finished. -
#wait(deadline: nil) ⇒ Object
Waits for the Execution and in-flight interjections, then returns the Run.
Constructor Details
#initialize(run, event_consumer: nil) ⇒ Execution
:nodoc:
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/little_ghost/execution.rb', line 38 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 @mutex = Mutex.new @condition = ConditionVariable.new @active_interjections = 0 @closing = false @task_runner = run.runtime.task_runner end |
Instance Attribute Details
#run ⇒ Object (readonly)
The supervised Run.
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. If the
work cannot start, this method closes run before raising.
The optional block receives each StreamEvent from the fiber or thread running the Execution. It must not depend on a particular thread and should not pause the scheduler or retain sensitive event content longer than the application requires.
33 34 35 |
# File 'lib/little_ghost/execution.rb', line 33 def start(run, &event_consumer) new(run, event_consumer:).send(:start) end |
Instance Method Details
#active? ⇒ Boolean
Indicates that the Execution or an interjection call is still active.
65 66 67 |
# File 'lib/little_ghost/execution.rb', line 65 def active? @mutex.synchronize { @state != :finished || @active_interjections.positive? } end |
#cancel ⇒ Object
Requests cooperative cancellation and returns self.
97 98 99 100 |
# File 'lib/little_ghost/execution.rb', line 97 def cancel run.cancellation_token.cancel self end |
#close(deadline: nil) ⇒ Object
Prevents new interjections, requests cancellation, and waits for shutdown.
The operation is idempotent. deadline has the same meaning as in #wait.
118 119 120 121 122 |
# File 'lib/little_ghost/execution.rb', line 118 def close(deadline: nil) @mutex.synchronize { @closing = true } cancel wait(deadline:) end |
#error ⇒ Object
Returns an event-delivery or cleanup exception raised by the Execution.
60 61 62 |
# File 'lib/little_ghost/execution.rb', line 60 def error @mutex.synchronize { @worker }&.error end |
#finished? ⇒ Boolean
Indicates that the Execution and all interjection calls have finished.
70 71 72 |
# File 'lib/little_ghost/execution.rb', line 70 def finished? !active? end |
#interject(payload = nil, **options) ⇒ Object
Prepares and delivers one interjection to the active run.
payload may be a message or a Hash containing message and the options
accepted by Run#interject. 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.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/little_ghost/execution.rb', line 81 def interject(payload = nil, **) if payload.nil? && .key?(:message) payload = .delete(:message) end interjection_started = false begin_interjection! interjection_started = true run.interject_with do prepared = run.prepare_interjection(interjection_payload(payload, )) interjection_arguments(prepared, ) end ensure finish_interjection! if interjection_started end |
#state ⇒ Object
Returns :pending, :running, or :finished.
55 56 57 |
# File 'lib/little_ghost/execution.rb', line 55 def state @mutex.synchronize { @state } end |
#wait(deadline: nil) ⇒ Object
Waits for the Execution and in-flight interjections, 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 Execution is re-raised after all supervised work finishes.
107 108 109 110 111 112 113 114 |
# File 'lib/little_ghost/execution.rb', line 107 def wait(deadline: nil) worker = wait_until_finished(deadline:) worker.wait caught = worker.error raise caught if caught run end |