pub trait PlanStore: Send + Sync {
// Required method
fn mark_applied<'life0, 'life1, 'async_trait>(
&'life0 self,
plan_id: Uuid,
applied_at: DateTime<Utc>,
routes: &'life1 [ProposedRoute],
) -> Pin<Box<dyn Future<Output = Result<Option<String>, ApplyError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
}Expand description
Persistence contract for plan_runs rows. Implementations: InMemoryPlanStore
(this file, for tests), PostgresPlanStore (lands in the cloud worker
crate when the sqlx-pool wiring is done).
Required Methods§
Sourcefn mark_applied<'life0, 'life1, 'async_trait>(
&'life0 self,
plan_id: Uuid,
applied_at: DateTime<Utc>,
routes: &'life1 [ProposedRoute],
) -> Pin<Box<dyn Future<Output = Result<Option<String>, ApplyError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn mark_applied<'life0, 'life1, 'async_trait>(
&'life0 self,
plan_id: Uuid,
applied_at: DateTime<Utc>,
routes: &'life1 [ProposedRoute],
) -> Pin<Box<dyn Future<Output = Result<Option<String>, ApplyError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Atomically (1) transition plan_id from status 'projected' to
'applied' and stamp applied_at, AND (2) persist routes to the
Gateway routing config the live gateway reads. Return the previous
status when the row exists, or None when no such row.
MUST be atomic across BOTH effects: the status flip and the route
write commit together or not at all. A partial update — status
flipped but routes not written, applied_at stamped but status
mismatched — violates the audit promise, because the plan.applied
chain entry asserts that the routes are now live. Implementations
MUST use a single transaction (Postgres: BEGIN; UPDATE plan_runs; INSERT INTO routes; COMMIT).
The store MUST only write routes when the transition actually
happens (previous status was 'projected'). When the row is already
in a terminal state, return the previous status and write nothing —
the free function apply_plan turns that into
ApplyError::InvalidState and emits no audit row.
routes is the caller’s authored route set (see
PlanResult::proposed_routes); it may be empty, in which case the
status flips and no routes are written (the legacy no-op shape, for
plan rows persisted before routes were carried on the result).
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".