lilydocs
HTTP APIWebSocketConsumer
Running the application2 min read

Cancellation and shutdown

Observe request cancellation and complete graceful application shutdown.

Cancellation signals that work should stop. The result proving that a resource has actually terminated and been cleaned up must be awaited separately. Lily preserves this distinction in both request and application lifecycles.

ExecutionCancellation#

The ExecutionCancellation received by actions, middleware, and guards provides is_cancelled, cancelled().await, and cloning. It is read-only; there is no public cancel or raw-token extraction API.

Long-running operations must observe the signal. PostgreSQL can receive this view directly. MongoDB and Redis require an explicit bridge to a separate operation token.

Request deadline#

The absolute deadline starts at admission. CORS, body reading, the action, response production, and transport writes share the same budget. An SSE heartbeat or stream chunk does not restart the clock.

A bounded cooperation window follows cancellation. An application response completed during this window can be preserved. An unfinished, uncommitted response may become 504 for a local timeout or 503 for shutdown. The status cannot change once a response has begun sending; the transport may be terminated instead.

Middleware cleanup#

on_request_termination(context, CleanupCancellation) applies to eligible middleware invocations interrupted abnormally. Invocations that were polled at least once but did not return normally are handled in reverse order. It is not a general finally hook for normally returned Ok or Err.

Store the required state in exchange.termination_state_mut() in advance. This store is separate from Request.local. The hook runs after execution/body/helper termination and before DI scope cleanup. It cannot write a response or call next.

Application shutdown#

start manages platform signals. Use start_with_cancellation(token) for external orchestration, or close().await through a cloned App for a separate handle. A successful build that was never started must also be closed.

Shutdown first stops new work, then terminates managed work and request resources, the application's container, and telemetry. External container/tracing owners complete their own shutdown.

Unfinished work#

It is not safe to assume that non-yielding CPU work, a blocking destructor, or an already started blocking file operation has been forcibly stopped. A timeout is not proof of completed cleanup. Design application code to cooperate with cancellation and make resource ownership explicit.

Sources for this page v0.1.0

This guide is based on the reviewed framework commit.

QUICK START
Documentation
Source code