Progress and output
Every executor has an EventBus for task lifecycle events.
from ttasks import TaskEvent, TaskEventType
seen: list[TaskEvent] = []
with executor.events.subscribed(seen.append):
executor.execute(task)
assert [event.type for event in seen] == [
TaskEventType.STARTED,
TaskEventType.SUCCEEDED,
]
For long-lived subscribers, use executor.events.subscribe(callback), which
returns an idempotent unsubscribe callable.
Event payloads
Events include:
type:STARTED,PROGRESS,OUTPUT,SUCCEEDED,FAILED,CANCELLED,BLOCKED, orPERSISTENCE_FAILEDtask_idtaskprevious_statusstatustimestamperror, when relevantprogress_percentandprogress_message, whentypeisPROGRESSoutput_streamandoutput_chunk, whentypeisOUTPUT
Subscriber exceptions do not fail task execution. They are recorded on
executor.events.errors so observers cannot break the work they observe.
Progress events
Handlers can report progress without changing task lifecycle state:
def handler(context):
context.emit_progress(25, "warming up")
context.emit_progress(message="still working")
return "done"
Progress percentages are optional finite values from 0 through 100. They are not required to be monotonic.
Streaming subprocess output
Built-in subprocess handlers emit OUTPUT events as stdout and stderr lines are
read. Complete stdout and stderr are still retained on the terminal
TaskResult.
Output subscribers run synchronously on reader threads, so keep callbacks fast.