Deadlines and cancellation
Use the shared normal pipeline deadline, cooperative cancellation and reserved cleanup time correctly.
delivery_execution_timeout_millis is the execution and cleanup budget for one delivery. It defaults to 30,000 ms and accepts 100–900,000 ms. Before hooks, guards, owner resolution, extraction, the handler and normal reverse after hooks share one absolute deadline. Each callback does not receive a fresh full timeout.
Read the remaining time in a handler#
use lilyrs::queue::{DeliveryCancellation, DeliveryDeadline, QueueHandlerError};
async fn check_work_budget(
cancellation: DeliveryCancellation,
deadline: DeliveryDeadline,
) -> Result<(), QueueHandlerError> {
if cancellation.is_cancelled() || deadline.remaining().is_zero() {
return Err(QueueHandlerError::retryable("WORK_INTERRUPTED"));
}
Ok(())
}This helper only checks whether time remains at that moment; it does not automatically bound I/O started later. A handler can receive these types as parts extractors. Explicitly adapt the deadline and cancellation to each external call; matching names do not imply conversions between different subsystem cancellation types.
Normal cutoff and shared reserve#
delivery start ───── normal pipeline cutoff P ───── hard cutoff H
before / guard / handler / after shared reserve
cooperation / termination
/ exact scope disposalThe reserve is the smaller of one quarter of the initial remaining budget and one second. For an initial 30-second budget, the normal pipeline therefore has roughly 29 seconds. Cooperation, abnormal middleware unwind and DI scope disposal share that reserve; they are not additional independent allowances.
At cutoff or execution cancellation, the framework first signals the read-only token, then continues polling the normal pipeline for at most 250 ms within the remaining local/root budget. If it returns during that window, its actual success or error is retained. Otherwise execution is dropped, while the retained cleanup owner continues with the invocation, entered middleware ledger and scope receipt.
A signal is not completion evidence#
Observe DeliveryCancellation through cancelled(), is_cancelled() and reason(). The application cannot cancel the framework token; express application rejection through a typed error. Closing admission alone does not create a delivery cancellation reason. Observing the signal does not mean cleanup or broker settlement has finished.
If a normal after hook is still pending, the pipeline is unfinished even when the handler has returned. Abnormal termination receives separate read-only cleanup cancellation and a deadline. A normal after hook that returned Ok or Err is not called again; interrupted cleanup callbacks are not retried either.
Relationship to shutdown and settlement#
During shutdown, delivery deadlines are capped by the shared application root deadline. settlement_timeout_millis is a separate local cap for ACK/NACK; it does not extend the root budget. Async timeouts cannot preempt CPU work that never yields or a blocking destructor. The shutdown report therefore distinguishes successful completion from missing termination evidence.
Sources for this page v0.1.0
This guide is based on the reviewed framework commit.