Date: 2026-05-11
Time: 15:44
This is an example script demonstrating FTL2's real-time event streaming system. It shows how modules can emit progress and log events to stderr during execution, and how calling code can consume those events via callbacks or post-execution from the result object. The file serves as both documentation and runnable reference for five streaming patterns: basic callbacks, Rich progress bars, simple text display, concurrent multi-task tracking, and post-hoc event access.
Run the full example suite:
uv run python example_streaming.py
Basic callback pattern — pass a function to event_callback:
result = await execute_local_streaming(
module_path,
{"steps": 5},
event_callback=on_event,
)
Rich progress bar — use EventProgressDisplay as a context manager:
display = EventProgressDisplay()
with display:
result = await execute_local_streaming(
module_path, params, event_callback=display.handle_event,
)
Concurrent tasks with per-task progress — use display.makecallback(taskid):
display = EventProgressDisplay()
async def run_task(task_id, task_name, duration):
callback = display.make_callback(task_id)
return await execute_local_streaming(module_path, params, event_callback=callback)
with display:
results = await asyncio.gather(
run_task("download", "Downloading package", 0.8),
run_task("extract", "Extracting files", 1.2),
)
No callback — events are still captured on result.events:
result = await execute_local_streaming(module_path, {})
for event in result.events:
print(event)
Module-side event protocol: Modules emit JSON objects to stderr, one per line. Two event types are shown:
{"event": "progress", "percent": int, "message": str, "current": int, "total": int, "taskid": str} — progress updates. taskid is used for multi-task disambiguation.{"event": "log", "level": "debug"|"info", "message": str} — log messages.Module input arrives on stdin as JSON with params under ANSIBLEMODULEARGS. Final result is printed to stdout as JSON.
Executor functions:
executelocalstreaming(modulepath, params, eventcallback=) — run a local module file with streaming.executelocalfqcn_streaming — imported but not demonstrated; presumably resolves modules by fully-qualified collection name.Display classes:
EventProgressDisplay — Rich-based progress bars; used as context manager. handleevent() for single task, makecallback(task_id) for multi-task.SimpleEventDisplay — text-only, prints on every 10% progress change. handle_event() method.result.events for post-hoc inspection.result.success and result.output provide the module's final return value (the stdout JSON).EventProgressDisplay must wrap execution in a with block to properly initialize and tear down the Rich display.asyncio.gather works — each task gets independent progress tracking when using makecallback(taskid).ftl2.moduleloading.executor: executelocalstreaming, executelocalfqcnstreaming — the core streaming execution layer.ftl2.progress: EventProgressDisplay, SimpleEventDisplay — display adapters for event streams.ANSIBLEMODULEARGS stdin/stdout contract, extended with stderr event streaming.