Skip to main content

Postgres

Struct Postgres 

Source
pub struct Postgres { /* private fields */ }

Implementations§

Source§

impl Postgres

Source

pub async fn apply_migrations( &self, module: &str, migrations: &[SqlMigration], ) -> Result<(), DbError>

Applies a module’s unapplied migrations in id order, tracked under <module>/<id> in a harness_migrations table; each migration runs in its own transaction so a failure rolls back atomically and re-running is idempotent. Mirrors SqliteDatabase::apply_migrations exactly.

§Errors

DbError::Batch when the tracking DDL or a migration’s SQL fails, or when the bookkeeping insert cannot be rendered.

Source

pub async fn apply_harness_migrations( &self, harness: &Harness, ) -> Result<(), DbError>

Applies every module’s migrations for a whole harness, in lock order: modules in harness (config) order, each set by zero-padded migration id — the order fz migrations collect pins in .harness-lock.json. For each module the postgres set applies when shipped, else the sqlite set when it passes the portable lint (select_set).

§Errors

DbError::Batch when a module’s sqlite set fails the lint or any migration fails to apply.

Source§

impl Postgres

Source

pub async fn bootstrap_registry(&self) -> Result<(), DbError>

Creates the harness_tenants registry on the control database, idempotently. Boot calls this first; a failure here aborts the boot (there is no registry to read, no DSN to resolve).

§Errors

DbError when the DDL fails.

Source

pub async fn register_tenant( &self, tenant: &str, dsn: &str, ) -> Result<(), DbError>

Registers (or re-points) a tenant: upsert the DSN and reset the status to provisioning — the next boot’s reconciliation is what promotes it to active.

§Errors

DbError when the write fails.

Source

pub async fn tenants(&self) -> Result<Vec<TenantRecord>, DbError>

Every tenant in the registry, newest DSN wins. The values come from the control database and include the DSN: callers log or serve with them, never print them.

§Errors

DbError when the read fails.

Source

pub async fn set_tenant_status(&self, tenant: &str, status: TenantStatus)

Records a tenant’s status. Best-effort by design (RECONCILIATION.md §6): a write that fails mid-boot still leaves the tenant refused at request time, because its pool was never registered.

Source

pub async fn reconcile_tenant( &self, record: &TenantRecord, harness: &Harness, ) -> Result<TenantReport, DbError>

Reconciles one tenant: take the advisory lock, then apply every module’s migrations to the tenant’s database in depends_on order. On any failure the tenant is marked degraded in the control database (best-effort) and the error is returned; the caller decides whether that aborts the boot (strict).

The tenant DSN is never part of any error message: connection strings carry credentials.

§Errors

DbError when the tenant’s database is unreachable or a migration fails.

Source

pub async fn reconcile_fleet( &self, harness: &Harness, parallelism: usize, ) -> Result<Vec<TenantReport>, DbError>

Reconciles every tenant in the registry whose status is active or provisioning, at most parallelism at a time (default 8; #30 §10 keeps the right number a measured question). A degraded tenant is left for the retry timer, not re-flown this boot.

This is what boot calls. The control database drives everything: if it cannot be bootstrapped or read, the error returns and the boot aborts — there is nothing useful to serve without a registry. A tenant that fails is marked degraded and every other tenant serves; the same with strict semantics is the caller’s decision (any Degraded in the reports).

§Errors

DbError when the control database cannot be bootstrapped or read. Per-tenant failures never abort the fleet.

Source

pub async fn reconcile_plan( &self, record: &TenantRecord, harness: &Harness, ) -> Result<TenantPlan, DbError>

What would be applied, per module, for one tenant. Takes the same advisory lock, so the answer is not a guess about a moving target (RECONCILIATION.md §8), and applies nothing.

§Errors

DbError when the tenant’s database is unreachable.

Source§

impl Postgres

Source

pub async fn connect(url: &str) -> Result<Self, DbError>

Opens a pool and establishes at least one connection, failing fast on an unreachable server or bad credentials.

Uses PoolLimits::default. A multi-tenant deployment wants Postgres::connect_with instead: one pool per tenant with no cap is how one busy tenant takes every connection on a shared cluster.

§Errors

DbError::Execute when the pool cannot connect.

Source

pub async fn connect_with( url: &str, limits: PoolLimits, ) -> Result<Self, DbError>

Opens a pool with explicit limits (TENANT-ROUTING.md §4).

sqlx caps and times out per pool, which is exactly the per-tenant boundary: a pool belongs to one tenant. The total across pools is not something sqlx can express, so it is not pretended to here — it needs a semaphore held by whatever owns the pools, acquired around every execute, query and batch. A config key that silently did nothing would be worse than its absence.

§Errors

DbError::Execute when the pool cannot connect.

Source

pub async fn close(&self) -> Result<(), DbError>

Closes the pool: waits for in-flight queries, then closes every connection. Dropping the adapter eventually closes the pool too; close makes shutdown deterministic for the parity kit and the native runtime.

§Errors

DbError::Execute when the pool cannot be closed.

Trait Implementations§

Source§

impl Clone for Postgres

Source§

fn clone(&self) -> Postgres

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Database for Postgres

Source§

fn batch_atomic<'life0, 'life1, 'async_trait>( &'life0 self, stmts: &'life1 [Statement], ) -> Pin<Box<dyn Future<Output = Result<(), DbError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Runs all statements in one transaction (atomic on Postgres).

Source§

fn execute<'life0, 'life1, 'async_trait>( &'life0 self, stmt: &'life1 Statement, ) -> Pin<Box<dyn Future<Output = Result<u64, DbError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn query<'life0, 'life1, 'async_trait>( &'life0 self, stmt: &'life1 Statement, ) -> Pin<Box<dyn Future<Output = Result<Rows, DbError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more