Cancels the in-flight Postgres query when the HTTP client disconnects (#82).
PostgREST cannot do this (postgrest#699, open since 2016): an accidental
unfiltered DELETE keeps running server-side after the client kills the
request. On the BEAM the disconnect is observable, so Bier ties it to a real
backend cancel:
- The request's database work runs in a
Tasklinked to the connection process, while the connection process arms the request socket (active: :once) and waits for either the task result or a socket close notification. - On disconnect the task is killed.
DBConnectionsees its client die mid-checkout and disconnects the connection, and Postgrex's protocol disconnect sends a wireCancelRequest(with the backend key) before closing — the PostgreSQL backend aborts the query instead of running it to completion, and the pool slot is re-established clean. [:bier, :query, :cancelled]is emitted (seeBier.Telemetry) and the request falls through toBier.Plugs.FallbackControlleras{:error, :client_disconnected}(a 499 nobody will receive, kept for request telemetry/logging symmetry).
Scope and limitations
- Disconnect detection watches the raw HTTP/1 socket (Bandit / ThousandIsland, TCP and SSL). Any other adapter shape falls back to running the work inline, exactly as before this module existed.
- The request body is fully read (
Bier.Plugs.ReadBody) before any query runs, so bytes arriving mid-query are only possible from a pipelining client. Such bytes are consumed by the watcher (they cannot be pushed back) and watching stops for that request — a non-issue for REST API clients, which do not pipeline.
Summary
Functions
Run fun (a zero-arity function performing the request's database work),
cancelling it if the HTTP client disconnects while it is in flight.
Functions
@spec run(Plug.Conn.t(), map(), (-> result)) :: result | {:error, :client_disconnected} when result: term()
Run fun (a zero-arity function performing the request's database work),
cancelling it if the HTTP client disconnects while it is in flight.
Returns fun's result, or {:error, :client_disconnected} after a
disconnect-triggered cancel. Raises/throws/exits from fun propagate
unchanged (same class, reason, and stacktrace) so error semantics are
identical to calling fun directly.