mempill_postgres/lib.rs
1//! # mempill-postgres
2//!
3//! PostgreSQL-backed `PersistencePort` adapter for mempill.
4//!
5//! ## Usage
6//!
7//! ```no_run
8//! use mempill_postgres::{open_postgres, PostgresEngine};
9//! use mempill_core::{EngineConfig, NoOpOracle, NoOpVector};
10//! use std::sync::Arc;
11//!
12//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
13//! let conn_str = "host=localhost port=5432 user=mempill dbname=mempill password=secret";
14//! let engine: PostgresEngine<NoOpOracle, NoOpVector> = open_postgres(conn_str, None, None, EngineConfig::default())?;
15//! # Ok(())
16//! # }
17//! ```
18//!
19//! ## Topology-b vs topology-a
20//!
21//! One backend per deployment: downstream consumers depend on EITHER `mempill-sqlite`
22//! OR `mempill-postgres`, never both.
23//!
24//! ## Concurrency model
25//!
26//! - r2d2 pool (max 20 connections) enables concurrent cross-agent transactions.
27//! - `pg_advisory_xact_lock(hashtext(agent_id)::bigint)` serializes same-agent writes at the DB level.
28//! - `UNIQUE(agent_id, stream_seq)` on `ledger_entries` provides OCC belt-and-suspenders against duplicate sequence numbers.
29//! - `requires_global_write_serialization()` returns `false` — EngineHandle skips the
30//! global write lock, enabling true Postgres concurrency across agents.
31
32// Embed migrations at compile time; no live DB needed to compile.
33refinery::embed_migrations!("migrations");
34
35mod connection;
36mod store;
37mod txn;
38
39pub use connection::{PostgresPersistenceStore, PostgresStoreError};
40pub use store::{open_postgres, open_postgres_with_oracle, PostgresPendingStore};
41pub use txn::PostgresTxn;
42
43/// Type alias for an `EngineHandle` backed by `PostgresPersistenceStore`.
44///
45/// `O` = OraclePort implementation, `V` = VectorPort implementation.
46pub type PostgresEngine<O, V> = mempill_core::EngineHandle<PostgresPersistenceStore, O, V>;