Event¶
Events are the messages that flow between entities. Every event has a target entity and a scheduled time.
Event types that form the fundamental units of simulation work.
Events drive the simulation forward. Each event represents something that happens at a specific point in simulation time. When invoked, an event calls its target entity's handle_event() method. For function-based dispatch, use Event.once() which wraps a function in a CallbackEntity.
This module also provides ProcessContinuation for generator-based multi-step processes, enabling entities to yield delays and resume execution later.
CompletionHook
module-attribute
¶
Signature for hooks that run when an event or process finishes.
Event ¶
Event(
time: Instant,
event_type: str,
target: Simulatable | None = None,
*,
daemon: bool = False,
on_complete: list[CompletionHook] | None = None,
context: dict[str, Any] | None = None,
)
The fundamental unit of simulation work.
Events are scheduled onto the EventHeap and processed in chronological order. Each event targets an Entity whose handle_event() method processes it.
For function-based dispatch without a full Entity, use the Event.once()
static constructor which wraps a function in a CallbackEntity.
Events support two additional mechanisms:
-
Generators: When handle_event() returns a generator, the simulation wraps it as a ProcessContinuation, enabling multi-step processes that yield delays between steps.
-
Completion Hooks: Functions registered via on_complete run when the event finishes (including after generator exhaustion). Used for chaining actions or notifying dependent entities.
Sorting uses (time, insertion_order) to ensure deterministic FIFO ordering for events scheduled at the same instant.
Attributes:
| Name | Type | Description |
|---|---|---|
time |
When this event should be processed. |
|
event_type |
Human-readable label for debugging and tracing. |
|
daemon |
If True, this event won't block auto-termination. |
|
target |
Entity to receive this event. |
|
on_complete |
Hooks to run when processing finishes. |
|
context |
Arbitrary metadata for tracing and debugging. |
cancel ¶
Mark this event as cancelled. The simulation loop will skip it on pop.
Cancelling an already-cancelled or already-processed event is a no-op.
trace ¶
Append a structured span to this event's application-level trace.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
action
|
str
|
Short action name (e.g., "handle.start", "process.yield"). |
required |
**data
|
Any
|
Extra structured fields for debugging. |
{}
|
add_completion_hook ¶
Attach a function to run when this event finishes processing.
Completion hooks enable dependency chains and notification patterns. For example, a QueueDriver uses hooks to know when its target entity has finished processing work and is ready for more.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hook
|
CompletionHook
|
Function called with the finish time when processing completes. |
required |
invoke ¶
Execute this event and return any resulting events.
Dispatches to the target entity's handle_event() method. If the handler returns a generator, it's automatically wrapped as a ProcessContinuation for multi-step execution.
Returns:
| Type | Description |
|---|---|
list[Event]
|
New events to schedule, including any from completion hooks. |
__lt__ ¶
- Time (Primary)
- Insert Order (Secondary - guarantees FIFO for simultaneous events)
once
staticmethod
¶
once(
time: Instant,
event_type: str,
fn: Callable[[Event], Any],
*,
daemon: bool = False,
context: dict[str, Any] | None = None,
) -> Event
Create a one-shot event that invokes a function.
Wraps the function in a CallbackEntity so that all events use target-based dispatch uniformly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
time
|
Instant
|
When this event should fire. |
required |
event_type
|
str
|
Human-readable label for debugging. |
required |
fn
|
Callable[[Event], Any]
|
Function called with the event. |
required |
daemon
|
bool
|
If True, won't block auto-termination. |
False
|
context
|
dict[str, Any] | None
|
Optional metadata dict. |
None
|
ProcessContinuation ¶
ProcessContinuation(
time: Instant,
event_type: str,
target: Simulatable | None = None,
*,
daemon: bool = False,
on_complete: list[CompletionHook] | None = None,
context: dict[str, Any] | None = None,
process: Generator | None = None,
)
Bases: Event
Internal event that resumes a paused generator-based process.
When an entity's handle_event() returns a generator, the simulation wraps it in a ProcessContinuation. Each invocation advances the generator to its next yield point, schedules another continuation for the yielded delay, and collects any side-effect events.
This enables entities to express multi-step, time-consuming operations naturally using Python's generator syntax:
def handle_event(self, event):
yield 0.05 # Wait 50ms for network latency
yield self.compute_time # Wait for processing
return self.create_response(event)
Yields are interpreted as:
- yield delay - Wait for delay seconds before resuming
- yield (delay, events) - Wait and also schedule side-effect events
- yield SimFuture() - Park until the future is resolved
Attributes:
| Name | Type | Description |
|---|---|---|
process |
The Python generator being executed incrementally. |
invoke ¶
Advance the generator to its next yield and schedule the continuation.
reset_event_counter ¶
Reset the global event counter to zero.
Called by Simulation.init() so each simulation run gets deterministic sort indices starting from 0.
enable_event_tracing ¶
Enable application-level event tracing (stack + trace spans).
Called by the visual debugger's serve() to enable per-event trace recording. When disabled (the default), Event.invoke() skips trace() and _ensure_stack() calls for better performance.