- (a) the register/unregister decide-and-queue critical sections: the refcount change and the derived LISTEN/UNLISTEN enqueue run under one registry guard (ChannelSet::enqueue_register/enqueue_unregister), so the command queue's order is the registry transitions' linearization — the old thread-preempted decide/send split (no await inside, but mid-unit preemption across workers) could leave a live refcount with the server-side LISTEN cleared until the next reconnect re-issue. The redundant per-registration LISTEN stays as the ack's vehicle, so a listen() that returned still awaits a server-processed LISTEN. - (b) a failed generation-verify no longer parks on the poll task forever: the bounded settle (LISTEN_SETTLE_TIMEOUT=2s, shutdown- selected) reaps a genuinely dead session promptly or aborts the alive-but-unusable connection's reaper at the bound — reconnect either way. - (c) close()/Drop can no longer leak the listener session: every listener-client query (verify batch, replay commands, serve commands) rides bounded_wait (LISTENER_QUERY_TIMEOUT=5s) with the shutdown watch selected alongside — the old unbounded run_command await sat outside the shutdown select; an overrun is the honest death posture (abort + reconnect, the snapshot re-issue recovers). - pins: the interleaved register/unregister server-model equality pin (with a decision-anchored deterministic finale), the bounded-wait + failed-verify-settle paused-time pins, and the black-hole-poxy harness pin (close reclaims the session past a stuck serve arm); the refcount unit pin reworked onto the decide-and-queue API. - replay-proofs (both ways, verified live): the old split shape fails the interleave pin on the review's exact mismatch; the old unbounded serve await fails the black-hole pin (session leaked past close). - the preserved postures re-verified green: reconnect survival, the fanout release guard, receivers-terminal-iff-loop-gone, the stale-UNLISTEN generation machinery, the register-failure unregister discipline, the poison-recovery idiom, and both POC-pinned deadlock-pitfall exclusions. - gates: pg suite with the harness server green (131 lib + 25 contract + 9 schema; lib battery run twice full), workspace build/test/fuzz gates server-less green, clippy -D warnings, fmt, and the rustdoc gate all green; task -> completed
alkstore-postgres
The Postgres engine of the alkstore
family: the core contract implemented on tokio-postgres +
deadpool-postgres, natively async (no blocking bridge, no
spawn_blocking seam), with a hand-rolled LISTEN forwarder.
let store = alkstore_postgres::open(&dsn, alkstore_postgres::PgOpts::default()).await?;
Engine posture — multi-host native. Connections are per-process
state; nothing assumes a shared host. Connection budget: max_size
pooled connections + 1 non-pooled listener connection per LISTEN-ing
process (pooled connections cannot carry LISTEN) — size the server
for the sum. v1 TLS is effectively unavailable: the engine hardwires
NoTls on every connection path, so network confidentiality must come
from the deployment topology. Queue/stream/lock/schedule tables live
in one engine-owned PostgreSQL schema (default alkstore,
per-engine option).
See the family README for the interface and the deployment matrix, and the Postgres engine spec for the driver's details.