pub struct PgStores { /* private fields */ }Expand description
Every Turnframe store over one PostgreSQL pool.
Implements ConversationStore,
InteractionStore,
CommandJournal,
EventJournal,
OutboxStore,
ReplayStore and
CommitStore, so a card written
through the interaction trait is the card a commit bundle settles.
Cloning shares the pool; it never opens new connections.
Implementations§
Source§impl PgStores
impl PgStores
Sourcepub async fn commit_in(
&self,
conn: &mut PgConnection,
account: &AccountId,
bundle: CommitBundle,
) -> Result<CommitReceipt, StoreError>
pub async fn commit_in( &self, conn: &mut PgConnection, account: &AccountId, bundle: CommitBundle, ) -> Result<CommitReceipt, StoreError>
Applies a bundle inside a transaction the caller owns.
This is the seam an adopter needs when the domain tables live in the same database as the stores: begin one transaction, run the workflow executor’s own writes on it, hand it to this method, and commit once. The journal admission still happens before execution, so recovery works the same way if the process dies — the transaction simply removes the window in which the domain state and the bookkeeping could disagree.
Nothing is committed here. Commit the transaction to make the bundle visible; drop it to discard the bundle along with your own writes.
use turnframe_core::ids::AccountId;
use turnframe_store::commit::CommitBundle;
use turnframe_store_postgres::PgStores;
let mut transaction = store.pool().begin().await?;
// ... the executor's own writes go here, on the same transaction ...
let receipt = store
.commit_in(&mut transaction, &AccountId::from("aurora"), bundle)
.await?;
transaction.commit().await?;§Errors
Any error an item would raise through its own store trait, plus the
refusals of CommitBundle::validate.
Source§impl PgStores
impl PgStores
Sourcepub async fn connect(url: &str) -> Result<Self, StoreError>
pub async fn connect(url: &str) -> Result<Self, StoreError>
Opens a pool on url with the default PgStoreConfig.
The URL is a standard PostgreSQL connection string
(postgres://user:password@host:port/database). It is never stored in a
field this type can print.
§Errors
Otherwhen the URL cannot be parsed,Unavailablewhen the first connection cannot be opened.
Sourcepub async fn connect_with(
url: &str,
config: &PgStoreConfig,
) -> Result<Self, StoreError>
pub async fn connect_with( url: &str, config: &PgStoreConfig, ) -> Result<Self, StoreError>
Opens a pool on url with config.
§Errors
Otherwhen the URL cannot be parsed,Unavailablewhen the first connection cannot be opened.
Sourcepub fn from_pool(pool: PgPool) -> Self
pub fn from_pool(pool: PgPool) -> Self
Uses a pool the caller already has.
Nothing is configured on it: the pool’s own settings, its search_path
and its statement timeout are whatever the caller set. Use this to share
one pool with the rest of an application, so the store and the domain
tables are reached through the same connections and can be enlisted in
the same transaction (see Self::commit_in).
Sourcepub fn with_schema(self, schema: impl Into<String>) -> Result<Self, ConfigError>
pub fn with_schema(self, schema: impl Into<String>) -> Result<Self, ConfigError>
Puts the tables of a caller-supplied pool in schema.
Only tells Self::migrate which schema to create; the pool must
already resolve to it, normally through a search_path in its connect
options.
§Errors
ConfigError::InvalidSchemaNamewhen the name is not a plain unquoted identifier.
Sourcepub async fn migrate(&self) -> Result<(), MigrateError>
pub async fn migrate(&self) -> Result<(), MigrateError>
Applies every migration this crate carries, creating the configured schema first when there is one.
It is safe to call on every start-up: sqlx records applied versions and
skips them, and the statements are written to be applied twice anyway.
Two processes racing it is safe too — the migrator takes a database-wide
advisory lock — though a deployment normally runs it once, before the
instances that will use the schema come up.
§Errors
MigrateErrorwhen the schema cannot be created, a migration fails, or an already-applied migration no longer matches its recorded checksum.
Sourcepub fn pool(&self) -> &PgPool
pub fn pool(&self) -> &PgPool
The pool underneath, for health checks, metrics, or statements this adapter does not make.
Sourcepub fn stores(&self) -> Result<Stores, StoresBuilderError>
pub fn stores(&self) -> Result<Stores, StoresBuilderError>
Bundles this store behind all seven traits.
§Errors
StoresBuilderError— never in practice. Every role is supplied here, and theResultexists only becauseturnframe-storeoffers no infallible “one backend for every role” constructor for a backend other than its own in-memory one.
Trait Implementations§
Source§impl CommandJournalReader for PgStores
impl CommandJournalReader for PgStores
Source§fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
) -> Pin<Box<dyn Future<Output = Result<CommandJournalEntry, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
) -> Pin<Box<dyn Future<Output = Result<CommandJournalEntry, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn for_turn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<Vec<CommandJournalEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn for_turn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<Vec<CommandJournalEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn pending_for_turn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<Vec<CommandJournalEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn pending_for_turn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<Vec<CommandJournalEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Pending or Executing, ordered by
created_at then command_id (spec §23.1: resume by idempotency key). Read moreSource§impl CommandJournalWriter for PgStores
impl CommandJournalWriter for PgStores
Source§fn begin<'life0, 'async_trait>(
&'life0 self,
entry: CommandJournalEntry,
) -> Pin<Box<dyn Future<Output = Result<JournalAdmission, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn begin<'life0, 'async_trait>(
&'life0 self,
entry: CommandJournalEntry,
) -> Pin<Box<dyn Future<Output = Result<JournalAdmission, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
UNIQUE (account_id, idempotency_key). Read moreSource§fn mark_executing<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn mark_executing<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn complete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
outcome: JournalOutcome,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn complete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
outcome: JournalOutcome,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
JournalOutcome::status. Recording the same outcome again on an
entry already in that status is accepted without change. Read moreSource§fn fail<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
error: &'life3 ExecutionError,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
fn fail<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
command_id: &'life2 CommandId,
error: &'life3 ExecutionError,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
JournalOutcome::from_execution_error. Same rules as
Self::complete. Read moreSource§impl CommitStore for PgStores
impl CommitStore for PgStores
Source§fn commit<'life0, 'life1, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
bundle: CommitBundle,
) -> Pin<Box<dyn Future<Output = Result<CommitReceipt, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn commit<'life0, 'life1, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
bundle: CommitBundle,
) -> Pin<Box<dyn Future<Output = Result<CommitReceipt, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
account atomically. Read moreSource§impl ConversationReader for PgStores
impl ConversationReader for PgStores
Source§fn load_conversation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 ConversationId,
) -> Pin<Box<dyn Future<Output = Result<ConversationRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn load_conversation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 ConversationId,
) -> Pin<Box<dyn Future<Output = Result<ConversationRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
account. Read moreSource§fn load_recent_turns<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
conversation: &'life2 ConversationId,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredTurn>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn load_recent_turns<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
conversation: &'life2 ConversationId,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredTurn>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
limit turns of a conversation in chronological
order (oldest of the selected first). Ordering is by received_at, then
turn_id. Read moreSource§fn load_turn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<StoredTurn, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn load_turn<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<StoredTurn, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn turn_phase<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<TurnPhaseMarker, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn turn_phase<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<TurnPhaseMarker, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn list_unfinished_turns<'life0, 'async_trait>(
&'life0 self,
scope: RecoveryScope,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<TurnPhaseMarker>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_unfinished_turns<'life0, 'async_trait>(
&'life0 self,
scope: RecoveryScope,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<TurnPhaseMarker>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
limit markers of turns whose phase is not terminal, oldest
first (by received_at, then turn_id). Read moreSource§impl ConversationWriter for PgStores
impl ConversationWriter for PgStores
Source§fn create_conversation<'life0, 'async_trait>(
&'life0 self,
record: ConversationRecord,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn create_conversation<'life0, 'async_trait>(
&'life0 self,
record: ConversationRecord,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn append_user_turn<'life0, 'async_trait>(
&'life0 self,
turn: StoredUserTurn,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn append_user_turn<'life0, 'async_trait>(
&'life0 self,
turn: StoredUserTurn,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
TurnPhase::Received. Read moreSource§fn append_assistant_turn<'life0, 'life1, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn: AssistantTurn,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn append_assistant_turn<'life0, 'life1, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn: AssistantTurn,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn set_turn_phase<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
phase: TurnPhase,
) -> Pin<Box<dyn Future<Output = Result<TurnPhaseMarker, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn set_turn_phase<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
phase: TurnPhase,
) -> Pin<Box<dyn Future<Output = Result<TurnPhaseMarker, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§impl EventJournalReader for PgStores
impl EventJournalReader for PgStores
Source§fn list_since<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
since: CaseRevision,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredEvent>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn list_since<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
since: CaseRevision,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredEvent>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
case_revision > since, in append order, at
most limit. since = CaseRevision::ZERO lists the whole history. Read moreSource§fn read_from<'life0, 'life1, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
after: EventCursor,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<EventPage, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_from<'life0, 'life1, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
after: EventCursor,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<EventPage, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_by_ids<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
ids: &'life2 [EventId],
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredEvent>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_by_ids<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
ids: &'life2 [EventId],
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredEvent>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
account, in the
order requested; unknown or foreign identifiers are omitted. Receipt
verification reads events back through this method (ADR-012 point 6). Read moreSource§fn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
) -> Pin<Box<dyn Future<Output = Result<u64, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
) -> Pin<Box<dyn Future<Output = Result<u64, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§impl EventJournalWriter for PgStores
impl EventJournalWriter for PgStores
Source§fn append<'life0, 'async_trait>(
&'life0 self,
batch: EventBatch,
) -> Pin<Box<dyn Future<Output = Result<Vec<EventId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn append<'life0, 'async_trait>(
&'life0 self,
batch: EventBatch,
) -> Pin<Box<dyn Future<Output = Result<Vec<EventId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn redact_payload<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
event_id: &'life2 EventId,
authority: &'life3 RedactionAuthority,
) -> Pin<Box<dyn Future<Output = Result<EventRedaction, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn redact_payload<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
event_id: &'life2 EventId,
authority: &'life3 RedactionAuthority,
) -> Pin<Box<dyn Future<Output = Result<EventRedaction, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Source§impl InteractionReader for PgStores
impl InteractionReader for PgStores
Source§fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 InteractionId,
) -> Pin<Box<dyn Future<Output = Result<InteractionRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 InteractionId,
) -> Pin<Box<dyn Future<Output = Result<InteractionRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
account. Read moreSource§fn list_open_for_conversation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
conversation: &'life2 ConversationId,
) -> Pin<Box<dyn Future<Output = Result<Vec<Interaction>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn list_open_for_conversation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
conversation: &'life2 ConversationId,
) -> Pin<Box<dyn Future<Output = Result<Vec<Interaction>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Active or Resolving) interactions of a conversation,
ordered by created_at then id. Read moreSource§fn list_open_for_case<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
) -> Pin<Box<dyn Future<Output = Result<Vec<Interaction>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn list_open_for_case<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
) -> Pin<Box<dyn Future<Output = Result<Vec<Interaction>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Active or Resolving) interactions of a case, ordered
by created_at then id. Read moreSource§fn blocking_answered_at<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
revision: CaseRevision,
) -> Pin<Box<dyn Future<Output = Result<bool, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn blocking_answered_at<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
revision: CaseRevision,
) -> Pin<Box<dyn Future<Output = Result<bool, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
case_key bound to revision has already
been answered by the user. Read moreSource§impl InteractionWriter for PgStores
impl InteractionWriter for PgStores
Source§fn insert<'life0, 'async_trait>(
&'life0 self,
interaction: Interaction,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn insert<'life0, 'async_trait>(
&'life0 self,
interaction: Interaction,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Active interaction. Read moreSource§fn insert_replacing_blocking<'life0, 'async_trait>(
&'life0 self,
interaction: Interaction,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn insert_replacing_blocking<'life0, 'async_trait>(
&'life0 self,
interaction: Interaction,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Active interaction, invalidating the Active blocking
occupant of the same case when there is one. Returns the identifiers it
invalidated (empty when the slot was free or the new card is not
blocking). Read moreSource§fn begin_resolution<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 InteractionId,
expected_status: InteractionStatus,
option_id: OptionId,
resolved_by: TurnId,
) -> Pin<Box<dyn Future<Output = Result<InteractionRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn begin_resolution<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 InteractionId,
expected_status: InteractionStatus,
option_id: OptionId,
resolved_by: TurnId,
) -> Pin<Box<dyn Future<Output = Result<InteractionRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
expected_status → Resolving, recording the chosen
option and the resolving turn. The only legal source status is
Active; the explicit parameter makes a lost race visible to the
caller instead of hiding it behind a re-read. Read moreSource§fn finish_resolution<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 InteractionId,
outcome: ResolutionOutcome,
) -> Pin<Box<dyn Future<Output = Result<InteractionRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn finish_resolution<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
id: &'life2 InteractionId,
outcome: ResolutionOutcome,
) -> Pin<Box<dyn Future<Output = Result<InteractionRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Resolving interaction. Read moreSource§fn invalidate_case_cards<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
reason: InvalidationReason,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn invalidate_case_cards<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
reason: InvalidationReason,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Active interaction of the case, whatever revision it
is bound to, and whether or not it declares revision independence.
Returns the invalidated identifiers in list order. Read moreSource§fn invalidate_for_case<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
new_revision: CaseRevision,
reason: InvalidationReason,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn invalidate_for_case<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
case_key: &'life2 CaseKey,
new_revision: CaseRevision,
reason: InvalidationReason,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Active interaction of the case that is bound to a
revision other than new_revision and does not declare revision
independence. Returns the invalidated identifiers in list order. Read moreSource§fn expire_due<'life0, 'async_trait>(
&'life0 self,
at: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn expire_due<'life0, 'async_trait>(
&'life0 self,
at: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<Vec<InteractionId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Active interaction whose expires_at <= now to Expired,
across all accounts. Returns the expired identifiers in list order. Read moreSource§impl OutboxReader for PgStores
impl OutboxReader for PgStores
Source§fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
) -> Pin<Box<dyn Future<Output = Result<OutboxRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
) -> Pin<Box<dyn Future<Output = Result<OutboxRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn list_for_command<'life0, 'life1, 'async_trait>(
&'life0 self,
command_id: &'life1 CommandId,
) -> Pin<Box<dyn Future<Output = Result<Vec<OutboxRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_for_command<'life0, 'life1, 'async_trait>(
&'life0 self,
command_id: &'life1 CommandId,
) -> Pin<Box<dyn Future<Output = Result<Vec<OutboxRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
created_at then id. Read moreSource§impl OutboxWriter for PgStores
impl OutboxWriter for PgStores
Source§fn enqueue<'life0, 'async_trait>(
&'life0 self,
entry: OutboxEntry,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn enqueue<'life0, 'async_trait>(
&'life0 self,
entry: OutboxEntry,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Pending entry. Read moreSource§fn claim_due<'life0, 'life1, 'async_trait>(
&'life0 self,
at: DateTime<Utc>,
limit: usize,
worker_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<OutboxEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn claim_due<'life0, 'life1, 'async_trait>(
&'life0 self,
at: DateTime<Utc>,
limit: usize,
worker_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<OutboxEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
limit due Pending entries for worker_id (see the
module documentation), oldest first by created_at then id, and
returns them already in Dispatching with attempt_count incremented. Read moreSource§fn mark_completed<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn mark_completed<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Dispatching | OutcomeUnknown → Completed; clears the claim and stamps
completed_at. Accepted without change when already Completed. Read moreSource§fn mark_failed<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
reason: String,
retry_at: Option<DateTime<Utc>>,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn mark_failed<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
reason: String,
retry_at: Option<DateTime<Utc>>,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
reason is a stable code, never free text, and is
stored on the record either way. Read moreSource§fn mark_outcome_unknown<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
remote_ref: Option<String>,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn mark_outcome_unknown<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
remote_ref: Option<String>,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Dispatching → OutcomeUnknown, releasing the claim and recording the
remote reference when the remote returned one (I15). Read moreSource§fn reschedule<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
next_attempt_at: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn reschedule<'life0, 'life1, 'async_trait>(
&'life0 self,
outbox_id: &'life1 OutboxId,
next_attempt_at: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Pending with next_attempt_at, releasing any
claim. Legal from Dispatching, OutcomeUnknown and Pending (which
only moves the time). Read moreSource§fn release_expired_claims<'life0, 'async_trait>(
&'life0 self,
claimed_before: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<Vec<OutboxId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn release_expired_claims<'life0, 'async_trait>(
&'life0 self,
claimed_before: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<Vec<OutboxId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Dispatching entry whose claim was taken strictly
before claimed_before back to Pending, due immediately. Returns the
released identifiers. Meant for a reaper that recovers entries a crashed
dispatcher left behind. Read moreSource§impl ReplayReader for PgStores
impl ReplayReader for PgStores
Source§fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<ReplayRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
turn_id: &'life2 TurnId,
) -> Pin<Box<dyn Future<Output = Result<ReplayRecord, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn list_for_conversation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
conversation: &'life2 ConversationId,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<ReplayRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn list_for_conversation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
account: &'life1 AccountId,
conversation: &'life2 ConversationId,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<ReplayRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
limit records of a conversation in chronological order
(by recorded_at, then turn_id). Read moreSource§impl ReplayWriter for PgStores
impl ReplayWriter for PgStores
Auto Trait Implementations§
impl !RefUnwindSafe for PgStores
impl !UnwindSafe for PgStores
impl Freeze for PgStores
impl Send for PgStores
impl Sync for PgStores
impl Unpin for PgStores
impl UnsafeUnpin for PgStores
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CommandJournal for T
impl<T> ConversationStore for T
impl<T> EventJournal for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> InteractionStore for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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