Postgres engine integration: StoreFactory (fresh schema per open, owned idempotent CASCADE teardown, isolation/idempotence pinned), the engine's backlog column (all ten rows green against the harness server — exemplar verified, the three ADR-023 rows verified not rewritten, the five engine-scoped rows, the new pg-arm PayloadTooLarge row discharging the SQLite task's deferred adoption), test-observation accessors cfg(test)-gated with the unused PgStore::new cut, stale stub-era doc text removed, lib docs stating the finished-engine posture (task pg-engine-integration)

This commit is contained in:
glm-5.3-flash committed 2026-10-09 10:22:25 +00:00
1 parent 77619c5e93
commit fb37da617d
7 files changed
+509 -59

No files matched your search

+7 -4
View File
@@ -27,10 +27,13 @@
//! 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.
//! The engine's surface re-exports as the consumer entry points:
//! [`open`] + [`PgOpts`] construct the store, [`PgStore`] is the
//! concrete type behind the [`alkstore::Store`] trait (the contract
//! surface), [`PgTxHandle`] the transaction seam, and the schema
//! module's bootstrap the DDL ground. The verification backlog's pg
//! column (the ADR-022 contract suite rows this engine owns) runs in
//! this crate's `contract_suite` test target.
mod forwarder;
mod lock;
+27 -43
View File
@@ -21,14 +21,6 @@
//! — the server session ends and the listener connection is released)
//! and the pool is closed; [`Drop`](PgStore::drop) delegates to
//! [`PgStore::close`]. Post-close trait ops fail closed (`Database`).
//!
//! No `spawn_blocking` seam on this engine (the crate docs' posture);
//! the trait stubs below are the wave-3 posture — they return
//! `Err(Database("… wiring lands with the … task"))` until the
//! mechanism tasks replace them. `notify`/`listen` are wired (the
//! notify-listen task's), `stream` (the streams task's), `queue` (the
//! queues task's), `try_lock` (the locks task's) — the wake
//! contract's pg arm rides the forwarder.
use alkstore::Store;
use std::sync::Arc;
@@ -54,10 +46,12 @@ pub struct PgStore {
pool: deadpool_postgres::Pool,
forwarder: Arc<Forwarder>,
schema: String,
/// Read by `listener_application_name()` below (the notify-listen
/// task's kill-targeting surface; tests exercise it now): gated in
/// the lib build until then.
#[cfg_attr(not(test), allow(dead_code))]
/// Test-observation surface (the kill-targetability probes assert
/// against the exact assigned name) — honestly `#[cfg(test)]`
///-gated; the name itself rides `listener_cfg` into the forwarder
/// (the reconnect re-issues carry it — that is the correctness
/// carrier, not this field).
#[cfg(test)]
listener_application_name: String,
closed: Arc<AtomicBool>,
}
@@ -82,23 +76,27 @@ impl PgStore {
}
/// The deadpool pool (queries/claims/non-transactional work) —
/// the mechanism tasks' access point (tests exercise it now):
/// gated in the lib build until the mechanism tasks wire it.
#[cfg_attr(not(test), allow(dead_code))]
/// test-observation surface for the engine's test modules
/// (`#[cfg(test)]`-gated; the lib build reaches the pool through
/// the trait wiring and `engine_ctx` directly).
#[cfg(test)]
pub(crate) fn pool(&self) -> &deadpool_postgres::Pool {
&self.pool
}
/// The forwarder handle (the wake substrate) — the mechanism
/// tasks' access point.
#[allow(dead_code)]
/// The forwarder handle (the wake substrate) —
/// test-observation surface for the engine's test modules
/// (`#[cfg(test)]`-gated; the lib build reaches the forwarder
/// through the trait wiring directly).
#[cfg(test)]
pub(crate) fn forwarder(&self) -> &Arc<Forwarder> {
&self.forwarder
}
/// The engine-owned schema name — the mechanism tasks'
/// schema-qualified SQL composition point (`quote_identifier`).
#[allow(dead_code)]
/// The engine-owned schema name — test-observation surface for the
/// engine's test modules (`#[cfg(test)]`-gated; the lib build
/// composes schema-qualified SQL from the field directly).
#[cfg(test)]
pub(crate) fn schema(&self) -> &str {
&self.schema
}
@@ -198,36 +196,22 @@ pub(crate) async fn open_store(config: &str, opts: PgOpts) -> alkstore::Result<P
let (client, connection) = listener_cfg.connect(NoTls).await.map_err(pg_error)?;
let forwarder = Forwarder::spawn(client, connection, listener_cfg);
Ok(PgStore::new(
Ok(PgStore {
pool,
forwarder,
forwarder: Arc::new(forwarder),
schema,
#[cfg(test)]
listener_application_name,
))
closed: Arc::new(AtomicBool::new(false)),
})
}
impl PgStore {
fn new(
pool: deadpool_postgres::Pool,
forwarder: Forwarder,
schema: String,
listener_application_name: String,
) -> PgStore {
PgStore {
pool,
forwarder: Arc::new(forwarder),
schema,
listener_application_name,
closed: Arc::new(AtomicBool::new(false)),
}
}
/// This store's listener `application_name` — the per-instance
/// `{prefix}-{pid}-{seq}` unique name (kill-targetable,
/// `pg_stat_activity`-assertable; deployment.md's ops note; the
/// notify-listen task's backend-kill tests target it — tests
/// exercise it now). Gated in the lib build until then.
#[cfg_attr(not(test), allow(dead_code))]
/// `pg_stat_activity`-assertable; deployment.md's ops note).
/// Test-observation surface, `#[cfg(test)]`-gated.
#[cfg(test)]
pub(crate) fn listener_application_name(&self) -> &str {
&self.listener_application_name
}
+1 -1
View File
@@ -616,7 +616,7 @@ async fn open_fails_database_on_unparseable_and_unreachable() {
/// tests' scope); `with_tx` surfaces the wired `begin_tx` naturally;
/// no panics.
#[tokio::test(flavor = "multi_thread")]
async fn store_trait_methods_are_wiring_stubs() {
async fn store_trait_methods_are_wired() {
let Some(dsn) = harness_dsn() else {
eprintln!("skip: no harness server");
return;