Skip to content

Cleanup and cancellation

The runnable track watcher demonstrates the core stream rule: close every EventStream in finally.

from picogrid_ecn_client import ECNClient, EntityCategory
async def consume(client: ECNClient) -> None:
stream = await client.entities.watch(categories={EntityCategory.TRACK})
try:
async for event in stream:
print(event.entity.id)
finally:
await stream.aclose()

Use an async client context so cleanup also runs after cancellation:

from picogrid_ecn_client import ECNClient, ECNConfig
async def run(config: ECNConfig) -> None:
async with ECNClient(config) as client:
await consume(client)

Unregister task handlers explicitly when their service lifetime ends. close() and unregister() are idempotent. Client close cancels tracked handlers, fails pending waiters with a typed local error, releases exact subscriptions, and bounds shutdown by shutdown_timeout. Async handlers must cooperate with cancellation; the client does not create or own worker threads for handler code.

Next, review the client and task lifecycle.

Version 0.2.0 · branch main