Skip to main content

PostgresStore

Struct PostgresStore 

Source
pub struct PostgresStore { /* private fields */ }
Expand description

Fixture reset is available only in the opt-in test_support module, never as a method on a normal store handle.

ⓘ
fn reset(store: &PostgresStore) {
    let _ = store.truncate_all();
}

Query-plan inspection, which refreshes database statistics, is likewise absent from the operational handle:

ⓘ
fn explain(store: &PostgresStore) {
    let _ = store.explain_active_lease_sum(AccountId(1));
}

The same holds for the two sweep plans (GL-65):

ⓘ
fn explain_sweep(store: &PostgresStore) {
    let _ = store.explain_reclaim_due_leases(jiff::Timestamp::UNIX_EPOCH, 256);
}
ⓘ
fn explain_rollover(store: &PostgresStore) {
    let _ = store.explain_due_periods("daily", 0, 256);
}

Implementations§

Source§

impl PostgresStore

Source

pub async fn connect( url: &str, policy: GrantPolicy, ) -> Result<Arc<Self>, StoreError>

Connect with default pool bounds and run pending migrations.

Source

pub async fn connect_with( url: &str, policy: GrantPolicy, pool_config: PoolConfig, ) -> Result<Arc<Self>, StoreError>

Connect and run pending migrations (versioned under ./migrations, tracked by sqlx’s _sqlx_migrations table — review finding GL-11).

Note the limits of what a pool bound can promise: acquire_timeout covers waiting for a connection, including establishing one, but a query already in flight on a healthy connection is bounded only by a server-side statement_timeout. Callers must still bound their own calls (INVARIANTS.md GL-18).

Source

pub async fn balance(&self, account: AccountId) -> Result<CostUnits, StoreError>

Source

pub async fn usage_recorded( &self, account: AccountId, ) -> Result<CostUnits, StoreError>

Source

pub async fn conservation( &self, account: AccountId, ) -> Result<Option<Conservation>, StoreError>

Trait Implementations§

Source§

impl AdminStore for PostgresStore

Source§

fn create_account<'life0, 'async_trait>( &'life0 self, config: AccountConfig, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, CreateAccountError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn deposit<'life0, 'async_trait>( &'life0 self, account: AccountId, units: CostUnits, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, AllocateError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn set_budget_schedule<'life0, 'async_trait>( &'life0 self, account: AccountId, schedule: Option<BudgetSchedule>, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, BudgetError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Give an account a periodic allowance, or take it away. Read more
Source§

fn account_view<'life0, 'async_trait>( &'life0 self, account: AccountId, ) -> Pin<Box<dyn Future<Output = Result<Option<AccountView>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

One account’s administrative state, or None if no such account (GL-121). Read more
Source§

fn roll_due_periods<'life0, 'async_trait>( &'life0 self, now: Timestamp, limit: NonZeroUsize, ) -> Pin<Box<dyn Future<Output = Result<RolloverBatch, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Cross the period boundary for up to limit accounts that are past it: expire each closed period’s unspent allowance and deposit the next one, one transaction per batch. Read more
Source§

fn set_account_status<'life0, 'async_trait>( &'life0 self, account: AccountId, status: AccountStatus, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<StatusChange>, SetStatusError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Set an existing account’s administrative status, in one transaction: the ledger’s status, and a republication of every live snapshot of that account carrying the new status at generation + 1. Read more
Source§

fn set_capacity_class<'life0, 'async_trait>( &'life0 self, account: AccountId, class: CapacityClass, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<StatusChange>, SetStatusError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Set an existing account’s execution-capacity class, in one transaction: the ledger’s class, and a republication of every live snapshot of that account carrying the new class at generation + 1 (GL-99). Read more
Source§

fn publish_snapshot<'life0, 'async_trait>( &'life0 self, principal: Principal, snapshot: PublishableSnapshot, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, PublishSnapshotError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Publish a principal’s compiled snapshot. Read more
Source§

fn remove_snapshot<'life0, 'async_trait>( &'life0 self, principal: Principal, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

impl KeyDirectory for PostgresStore

Source§

fn credential_activity<'life0, 'life1, 'async_trait>( &'life0 self, keys: &'life1 [KeyId], ) -> Pin<Box<dyn Future<Output = Result<Vec<CredentialActivity>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Inspect requested keys in input order, including repeated IDs and retired keys. Every input has one explicit result or the read fails. This operator read uses O(keys.len()) output memory; backends bound individual queries internally. Multiple chunks need not share an instant.
Source§

fn insert_key<'life0, 'async_trait>( &'life0 self, record: KeyRecord, ) -> Pin<Box<dyn Future<Output = Result<(), KeyError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Record a minted credential. The caller has already generated the secret and computed its digest; this stores what remains.
Source§

fn revoke_key<'life0, 'async_trait>( &'life0 self, key_id: KeyId, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<Revocation, KeyError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Retire one credential, reporting whether it was live. Read more
Source§

fn revoke_key_audited<'life0, 'async_trait>( &'life0 self, key_id: KeyId, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<Revocation>, KeyError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Retire a credential and capture its actual owner, key and predecessor under the mutation lock. A repeated revocation returns equal states.
Source§

fn publish_key_snapshot<'life0, 'async_trait>( &'life0 self, account: AccountId, key: KeyId, snapshot: PublishableSnapshot, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, KeySnapshotError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Publish snapshot for the principal of account’s credential key, resolved inside the store (GL-143). Read more
Source§

fn remove_key_snapshot<'life0, 'async_trait>( &'life0 self, account: AccountId, key: KeyId, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, KeySnapshotError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Withdraw the snapshot of account’s credential key, tombstoning it as AdminStore::remove_snapshot does. Allowed for a revoked credential: revocation does not withdraw its snapshot, and withdrawal is the safe direction.
Source§

fn active_keys<'life0, 'async_trait>( &'life0 self, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<Vec<KeyRecord>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Unbounded operator read of every credential valid at now. Serving instances use KeySource pages and an owned, bounded drain instead. Retained for existing direct-store lifecycle tooling; no hidden page cap.
Source§

fn account_keys<'life0, 'async_trait>( &'life0 self, account: AccountId, after: Option<KeyId>, limit: NonZeroUsize, ) -> Pin<Box<dyn Future<Output = Result<Vec<KeySummary>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

One account’s credentials, ordered by key_id, for an operator listing (GL-121). Read more
Source§

fn insert_key_within<'life0, 'async_trait>( &'life0 self, record: KeyRecord, max_active: NonZeroUsize, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<(), KeyError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Record a credential only if the account holds fewer than max_active live ones, counting and inserting indivisibly (GL-121). Read more
Source§

fn insert_key_within_audited<'life0, 'async_trait>( &'life0 self, record: KeyRecord, max_active: NonZeroUsize, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<AdminReceipt<()>, KeyError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Bounded issuance with lifecycle evidence captured under the mutation lock. HTTP administrators must use this receipt rather than synthesize history.
Source§

impl KeySource for PostgresStore

Source§

fn active_keys_page<'life0, 'async_trait>( &'life0 self, now: Timestamp, after: Option<KeyId>, limit: NonZeroUsize, ) -> Pin<Box<dyn Future<Output = Result<KeyPage, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Read active records in strictly increasing key-id order. Direct stores use now; HTTP servers choose their own clock and return it as as_of. Reads must be coherent with the returned revision, including for an empty result. Never return a partial successful page after a failure.
Source§

impl LeaseAllocator for PostgresStore

Source§

fn acquire<'life0, 'async_trait>( &'life0 self, account: AccountId, requested: CostUnits, ttl: SignedDuration, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<Allocation, AllocateError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Atomically debit a grant from the account. The granted size follows the backend’s GrantPolicy and may be smaller than requested; the fencing token comes from a strictly increasing per-account sequence. It remains a capability for this lease only; allocating a newer token does not invalidate another active lease.
Source§

fn release<'life0, 'async_trait>( &'life0 self, lease_id: LeaseId, fencing_token: FencingToken, unspent: CostUnits, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<(), AllocateError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Graceful return: require the stored (lease_id, fencing_token) pair, credit unspent back, and close the lease. Callers should flush usage first when possible; events arriving after release are accepted only when they fit its provisional settlement loss.
Source§

fn consolidate<'life0, 'async_trait>( &'life0 self, lease_id: LeaseId, fencing_token: FencingToken, unspent: CostUnits, requested: CostUnits, needed: CostUnits, ttl: SignedDuration, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<Allocation, AllocateError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Atomically return an active lease’s unspent units and re-grant against the restored balance: release followed by acquire, in one transaction, for the same account the lease names. Read more
Source§

fn reclaim_expired_batch<'life0, 'async_trait>( &'life0 self, now: Timestamp, limit: NonZeroUsize, ) -> Pin<Box<dyn Future<Output = Result<ReclaimBatch, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Settle at most limit active leases whose TTL (plus the policy’s reclaim grace) has lapsed and whose holder never released them. Read more
Source§

fn reclaim_expired<'life0, 'async_trait>( &'life0 self, now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<Vec<ReclaimedLease>, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Settle every currently expired lease through bounded transactions. Read more
Source§

impl SnapshotSource for PostgresStore

Source§

fn principals<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<Principal>>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Tombstones included, for the reason MemoryStore::principals gives: forgetting a revoked principal is how one gets resurrected.

A primary-key scan, so no new index — the table holds one row per principal, not per request, and ORDER BY makes the result stable so a caller diffing two enumerations sees real changes rather than storage order.

Source§

fn snapshot<'life0, 'async_trait>( &'life0 self, principal: Principal, ) -> Pin<Box<dyn Future<Output = Result<SnapshotResolution, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Fetch the authoritative state for a principal. Revocation is distinct from never-known so pull, lag recovery, and restart preserve the generation watermark required for anti-resurrection semantics. Reads used to reconstruct reclaimed local history must be linearizable against durable publications/tombstones. Start a new source operation; an earlier cached response or lagging replica cannot establish that principal’s forgotten generation floor. Return an error if this authority is unavailable. MemoryStore and primary PostgresStore reads supply this ordering; HTTP deployments must preserve it end to end.
Source§

fn subscribe(&self) -> Receiver<SnapshotPush>

Subscribe to pushes. A lagging receiver may miss updates; the contract is that a fresh snapshot() fetch after a lag error observes at least the newest generation.
Source§

impl StoreHealth for PostgresStore

Source§

fn ping<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

impl UsageSink for PostgresStore

Source§

fn ingest<'life0, 'life1, 'async_trait>( &'life0 self, events: &'life1 [UsageEvent], _now: Timestamp, ) -> Pin<Box<dyn Future<Output = Result<IngestReport, IngestError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Record a batch. Idempotent on request_id; every event must match its stored (lease_id, account_id, fencing_token) capability before lease state and accounting capacity are checked. Partial acceptance is normal — the report says what happened. Read more

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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, 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