- notify: auto-commit pg_notify path, 8000-byte typed client-side check
through the tx seam's NOTIFY_PAYLOAD_LIMIT (one limit owner), closed-store
fail-closed before payload work
- listen: acked synchronous channel registration (listen starts-from-now —
a notify racing the LISTEN cannot be lost), refcounted ChannelSet
(UNLISTEN at last-subscriber drop), PgWakeReceiver bridging Wake { channel }
only, channel-scoped fanout + reserved reconnect-wake to every subscriber,
Lagged(n) surfaced-not-silent
- receiver close semantics (ADR-021 §5 pg arm): stays open across forwarder
reconnects, terminal None only at engine shutdown — Forwarder::shutdown
takes the fanout sender so receiver-held Arc lifetimes can't pin the
broadcast open
- tests: wake-arrives, 7999/8000/8002 boundary both entry points, no-replay
during connection gaps, backend-kill reconnect through the receiver stack,
drop-unregisters (behavioral probe — pg_listening_channels is per-session),
validation both paths, the two POC deadlock pitfalls re-pinned, 11 new
tests green against the harness server, gates green server-less
(task pg-engine-notify-listen)
51 lines
2.0 KiB
Rust
51 lines
2.0 KiB
Rust
//! alkstore-postgres — the Postgres engine: the core contract
|
|
//! implemented on tokio-postgres + deadpool-postgres (ADR-001,
|
|
//! ADR-004).
|
|
//!
|
|
//! # Posture
|
|
//!
|
|
//! **Multi-host by nature** (ADR-016): connections are per-process
|
|
//! state; nothing assumes a shared host — this engine's deployment
|
|
//! boundary is its crate identity (compile-time engine discovery:
|
|
//! pick this crate, get this posture). No runtime capability surface.
|
|
//! The per-process connection budget is `max_size` pooled connections
|
|
//! **+ 1 non-pooled listener connection per LISTEN-ing process** (the
|
|
//! forwarder; deadpool#360 — pooled connections cannot deliver;
|
|
//! deployment.md's budget line) — consumers size their server for the
|
|
//! sum.
|
|
//!
|
|
//! **Natively async** (ADR-004/ADR-007): no blocking bridge, no
|
|
//! `spawn_blocking` seam — the driver's client is `Send + Sync` and
|
|
//! the tx handle holds the pooled object directly (POC #2
|
|
//! compile-probe verified). Every engine call is a straight `.await`.
|
|
//!
|
|
//! Durability knobs, pool sizing, and the engine-owned schema name are
|
|
//! engine-configuration concerns on [`PgOpts`] (ADR-008 §6) — never
|
|
//! contract surface: `synchronous_commit` per-session (ship config on,
|
|
//! ADR-004/deployment.md's measured trade), `max_size` the deadpool
|
|
//! bound, `schema` the one engine-owned PostgreSQL schema (ADR-010 §8,
|
|
//! default `alkstore`; co-tenancy with consumer tables is the
|
|
//! deployment posture).
|
|
//!
|
|
//! Wave 4 build order: schema bootstrap (this module — the dependency
|
|
//! root), then `open`/`PgOpts` + pool + listener wiring, the tx seam,
|
|
//! the LISTEN forwarder, the mechanisms (queues, streams, locks,
|
|
//! scheduler/outbox); each task replaces the prior stubs.
|
|
|
|
mod forwarder;
|
|
mod notify;
|
|
mod opts;
|
|
mod resolution;
|
|
mod schema;
|
|
mod seam;
|
|
mod store;
|
|
mod tx;
|
|
|
|
pub use opts::{DEFAULT_MAX_SIZE, PgOpts};
|
|
pub use schema::{
|
|
BootstrapError, BootstrapResult, DEFAULT_SCHEMA, QualifiedTable, bootstrap, quote_identifier,
|
|
tables,
|
|
};
|
|
pub use store::{PgStore, open};
|
|
pub use tx::PgTxHandle;
|