Skip to content

cayu.storage.PostgresBudgetLedger

Part of cayu.storage.postgres. Read the Python API overview and install the required extra.

from cayu.storage import PostgresBudgetLedger

Postgres-backed atomic budget reservation ledger for multi-worker apps.

reserve serializes per budget (scope/key/window/currency) under a transaction-scoped advisory lock, so concurrent workers on separate connections cannot jointly overshoot max_estimated_cost; reconcile and release row-lock the reservation with SELECT ... FOR UPDATE. The cayu_budget_reservations table is owned by the shared migration machinery (ADR 0001 revision 8).

Bases: _PostgresStoreBase, BudgetLedger.

PostgresBudgetLedger.__init__(conninfo: str | None=None, *, pool: AsyncConnectionPool | None=None, min_size: int=1, max_size: int=8, schema_mode: schema.SchemaMode=schema.SchemaMode.VALIDATE, clock: Callable[[], datetime] | None=None, reservation_ttl_seconds: int | None=DEFAULT_RESERVATION_TTL_SECONDS) -> None
async PostgresBudgetLedger.ensure_schema() -> None

Open the pool and reconcile the schema now (per schema_mode).

Normally reconciliation happens lazily on first use; the cayu storage CLI calls this to run a migrate (or validate) as an explicit step.

async PostgresBudgetLedger.close() -> None
async PostgresBudgetLedger.reserve_batch(*, members, binding_id=None, binding_authority_digest=None, binding_allowance=None, binding_consumption_id=None) -> BudgetBatchResult

Reserve all ceilings in one PostgreSQL transaction.

async PostgresBudgetLedger.register_budget_binding(*, binding_id: str, authority_digest: str, allowance: int) -> None
PostgresBudgetLedger.durable_state_paths() -> tuple[Path, ...]

Return local files that hold this ledger’s durable state.

async PostgresBudgetLedger.claim_reservation_identity(*, reservation_id: str, publication_session_id: str, publication_id: str) -> None
PostgresBudgetLedger.reservation_ttl_seconds() -> int | None
async PostgresBudgetLedger.heartbeat(*, reservation_id: str) -> bool
async PostgresBudgetLedger.mark_dispatched(*, reservation_ids: tuple[str, ...], dispatch_id: str, dispatched_at: datetime | None=None) -> tuple[BudgetReservationRecord, ...]
async PostgresBudgetLedger.release_pre_provider_dispatch(*, reservation_ids: tuple[str, ...], dispatch_id: str, reason: str, occurred_at: datetime | None=None) -> tuple[BudgetReconciliation, ...]
async PostgresBudgetLedger.reserve(*, reservation_id: str | None=None, limit: BudgetLimit, session_id: str, agent_name: str, provider_name: str, model: str, model_attempt_identity: ModelAttemptIdentity, environment_name: str | None=None, settlement_event_payload: dict[str, Any] | None=None, settlement_fallback: BudgetSettlementFallback | None=None, requested_amount: Decimal | None=None, billing_identity: BillingIdentity | None=None, effective_at: datetime | None=None) -> BudgetReservationResult
async PostgresBudgetLedger.reconcile(*, reservation_id: str, actual_amount: Decimal, settlement_kind: Literal['completed', 'conservative']='completed', reason: str | None=None, occurred_at: datetime | None=None, billing_identity: BillingIdentity | None=None, pricing: BudgetReconciliationPricing | None=None) -> BudgetReconciliation
async PostgresBudgetLedger.release(*, reservation_id: str, reason: str, occurred_at: datetime | None=None) -> BudgetReconciliation
async PostgresBudgetLedger.load_reservation(reservation_id: str) -> BudgetReservationRecord | None
async PostgresBudgetLedger.load_settlement(settlement_id: str) -> BudgetSettlementRecord | None
async PostgresBudgetLedger.list_pending_settlements(*, session_id: str | None=None, after: BudgetSettlementCursor | None=None, limit: int=100) -> list[BudgetSettlementRecord]
async PostgresBudgetLedger.mark_settlement_event_published(*, settlement_id: str, event_id: str) -> BudgetSettlementRecord

Release source · Runtime guarantees · Capability guides