Skip to main content

PlanStore

Trait PlanStore 

Source
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§

Source

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".

Implementors§