pub trait Cancellable: Send + Sync {
// Required method
fn cancel(&self);
}Expand description
Anything that can signal the server to abort the query currently running on an associated connection.
Implementations must be Send + Sync so that streaming result types can
hold a &dyn Cancellable across await points and thread boundaries.
§Guarantees
cancel()is fire-and-forget. It does not block waiting for the server to acknowledge the cancel or for the in-flight query to actually stop. Callers that need to observe the query’s final state should drain the original connection (seesuper::connection::RawConnection::drain_until_ready_bounded).cancel()never panics and never returns an error. Any transport-level failures (e.g. the cancel connection can’t be opened) are logged and swallowed. This keepscancel()usable fromDropimpls, which cannot propagate errors.cancel()is idempotent and late-safe. It is always possible for the in-flight query to complete between the moment a caller decides to cancel and the moment the cancel actually reaches the server — the query’s naturalReadyForQueryand the cancel request race. Both PG wire and gRPC handle this correctly: the PG wireCancelRequesttravels on a separate connection and only affects the query currently bound to the target connection’s process id, so a cancel that arrives after the query finished targets nothing and is a harmless no-op; the gRPCcancel_queryRPC is similarly keyed on a server-assigned query id and returns gracefully when the id corresponds to a completed query. Connection-pool state is never affected by a late cancel, because cancels never mutate the underlying connection’s protocol state — they only signal the server to abort work on an already-separately-tracked query.
§Writing an implementation
Cancellable is an internal cleanup abstraction, not a user-facing
cancel API. Most transports already have a natural
pub fn cancel_...(..) -> Result<(), TransportError> method that users
call directly when they want error-aware cancellation (metrics, retry,
user feedback, etc). A Cancellable impl is a thin wrapper around that
fallible API that swallows transport errors (logged via
tracing::warn!) so the trait method can satisfy its no-error
guarantee.
The canonical example is
impl Cancellable for super::client::Client,
which wraps the fallible
Client::cancel PG wire
CancelRequest method:
impl Cancellable for Client {
fn cancel(&self) {
if let Err(e) = Client::cancel(self) {
tracing::warn!(error = %e, "cancel failed (swallowed)");
}
}
}The gRPC transport has the same fallible user API
(GrpcClient::cancel_query)
but no Cancellable impl today — gRPC has no streaming result type
whose Drop would consume &dyn Cancellable, and Cancellable::cancel
takes no arguments so it cannot be implemented directly on GrpcClient
(which doesn’t know which query_id to cancel). A future gRPC
streaming type will introduce a per-query handle along the lines of
GrpcCancelHandle { client, query_id } that implements Cancellable
by wrapping and swallowing GrpcClient::cancel_query.