What is Invoke and how does it work?
developThe invoke mechanism allows a state to spawn external work (such as API calls, file I/O, or child state machines) when it is entered. This work runs for the duration of the state and is automatically cancelled when the state is exited, following SCXML <invoke> semantics.
Execution Model
Invoke handlers run outside the main state machine processing loop:
- Sync engine: Each handler runs in a daemon thread.
- Async engine:
- Sync handlers: Run in a thread executor (
loop.run_in_executor) wrapped in anasyncio.Taskto prevent blocking the event loop. - Coroutine functions and
IInvokehandlers withasync def run(): These are awaited directly on the event loop, making them ideal for non-blocking async I/O (e.g.,aiohttp).
- Sync handlers: Run in a thread executor (
Lifecycle Events
- Completion: When a handler finishes, a
done.invoke.<state>.<id>event is sent to the machine. The return value of the handler is passed as thedatakeyword argument to callbacks on the target state. - Error: If a handler raises an exception, an
error.executionevent is sent. - Cancellation: If the state is exited before completion, the invocation is cancelled.
ctx.cancelledis set andon_cancel()is called onIInvokehandlers.