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:
1 parent
77619c5e93
commit
fb37da617d
7 files changed
+509
-59
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user