run() is where your model’s logic lives. It’s an async method that the runtime calls once after load() and runs for the lifetime of the model. You have full control over what happens inside it.
Basic pattern
- Run your forward pass.
- Call
emit()to send the output to the client. - Check
self.connected.is_set()to know if the client is still there.
run(), the default blocks forever. This is useful for purely event-driven models where all logic lives in @event handlers.
Connection signal
self.connected is an asyncio.Event that the runtime manages. It is set when a client connects and cleared when they disconnect.
@connected handler fires and cleared before your @disconnected handler fires.
Emitting frames
Callemit() to send an Output instance to the client:
fps.
Batches
emit() accepts both single frames (H, W, 3) and batches (N, H, W, 3). When you pass a batch, the runtime splits it into individual frames and emits them at the target rate. Always pass the full batch in a single emit() call:
Blocking
If the output queue is full,emit() awaits until a slot opens. This is the natural throttle point: when the model produces faster than the emission rate, it pauses here:
drop=True to discard the frame instead of blocking:
Adaptive frame rate
Report how long inference took so the runtime adjusts the emission rate to match your model’s throughput:FPS and buffer size
Set these as class attributes on yourReactorModel subclass:
fps sets the target output frame rate (default 30). buffer_size sets the output queue depth (default 4). Higher values smooth out jitter but add latency.
If your model emits frames in batches, set buffer_size to at least double the batch size:
Dynamic FPS
Change the frame rate at any point during the model’s lifecycle:Sending messages
Send structured data to the client from insiderun():
Concurrency
@event handlers fire concurrently with run() at any await point. If you read an instance attribute, do an await, and read it again, a handler may have changed it in between. Snapshot values into local variables before expensive operations:
Next
Managing State
Instance attributes, explicit events, and concurrency.
Events & Messages
Custom events, lifecycle hooks, and outbound messages.