falaw.events#

Structured progress events for fal calls.

Replaces the implicit “stream raw log strings to stdout” model with a small, machine-readable event stream that orchestrators can subscribe to (UI progress bars, cost telemetry, billing dashboards, etc.).

A ProgressEvent is emitted at every major lifecycle transition of a single call_fal invocation:

  • queued — call submitted to fal

  • progress — fal pushed an InProgress update with no message body

  • log — fal pushed an InProgress update with a log line

  • done — call returned a result

  • error — call raised

  • cache_hit — falaw.cached_call_fal() found a hit and skipped the network

Subscribers can be registered globally via subscribe() or per-call via the on_event= argument on call_fal() / cached_call_fal(). The on_log parameter still works (legacy: a string-only stream); see call_fal() for compatibility notes.

Functions

clear_subscribers()

Drop all registered subscribers.

emit(event, *[, also])

Send event to every registered subscriber + the also list.

subscribe(callback)

Register callback to receive every emitted ProgressEvent.

unsubscribe(callback)

Remove a previously subscribe()'d callback.

Classes

ProgressEvent(*, kind, application, call_id)

One step in the lifecycle of a fal call.

class falaw.events.ProgressEvent(*, kind, application, call_id, message='', pct=None, elapsed_s=0.0)[source]#

Bases: object

One step in the lifecycle of a fal call.

kind#

Lifecycle stage. See EventKind.

application#

fal model id (e.g. "fal-ai/flux/dev").

call_id#

A short hex string that uniquely identifies the call. All events for one call_fal invocation share the same call_id.

message#

Free-form text. For "log" events this is the log line; for "error" it’s repr(exc); otherwise empty.

pct#

Optional progress percentage in [0.0, 100.0]. fal’s current API doesn’t surface this; included for forward compatibility.

elapsed_s#

Seconds since the call started.

falaw.events.clear_subscribers()[source]#

Drop all registered subscribers. Mostly for tests.

Return type:

None

falaw.events.emit(event, *, also=())[source]#

Send event to every registered subscriber + the also list.

Subscriber exceptions are swallowed (with a printed warning) so a misbehaving UI hook can’t bring the rendering pipeline down.

Return type:

None

falaw.events.subscribe(callback)[source]#

Register callback to receive every emitted ProgressEvent.

Returns the callback unchanged so it can be used as a decorator:

@subscribe
def log_to_file(ev: ProgressEvent) -> None:
    ...
Return type:

Callable[[ProgressEvent], None]

falaw.events.unsubscribe(callback)[source]#

Remove a previously subscribe()’d callback. No-op if absent.

Return type:

None