pub struct LauncherSagaLog {
conn: Mutex<Connection>,
}Expand description
SQLite-backed launcher saga log. Owned by SagaCoordinator as
Arc<LauncherSagaLog> once PR LSD-2 wires it; PR LSD-1 only
constructs and tests it in isolation.
Fields§
§conn: Mutex<Connection>Implementations§
Source§impl LauncherSagaLog
impl LauncherSagaLog
Sourcepub fn open(path: &Path) -> Result<Self, LogError>
pub fn open(path: &Path) -> Result<Self, LogError>
Open a saga log backed by the given SQLite file. Configures
WAL mode + 5s busy timeout + foreign_keys=ON (mirroring
SagaLog::open in agentmux-srv/src/sagas/log.rs) and
applies the schema migration from schema.rs.
Idempotent: reopening the same DB applies the same DDL via
CREATE TABLE IF NOT EXISTS — no double-creation, no error.
Sourcepub fn open_read_only(path: &Path) -> Result<Self, LogError>
pub fn open_read_only(path: &Path) -> Result<Self, LogError>
Open the saga log in read-only mode. Used by --diag sagas
so an operator’s diagnostic invocation can’t accidentally
schema-migrate or modify a log that a running launcher owns.
Skips configure_and_migrate (read-only opens shouldn’t run
migrations) and skips the foreign_keys=ON pragma since we
don’t write. (codex P2 PR #647 round 3.)
Sourcepub fn open_in_memory() -> Result<Self, LogError>
pub fn open_in_memory() -> Result<Self, LogError>
Open an in-memory saga log for testing. Used by tests.rs
and by future PR LSD-2 coordinator integration tests.
fn configure_and_migrate(conn: Connection) -> Result<Self, LogError>
Sourcepub fn max_saga_id(&self) -> Result<u64, LogError>
pub fn max_saga_id(&self) -> Result<u64, LogError>
Highest existing saga_id in the durable log, or 0 if empty.
PR LSD-2 calls this at coordinator startup to seed
next_saga_id so a launcher restart doesn’t reuse ids that
already have rows in the log.
Sourcepub fn start_saga(
&self,
saga_id: u64,
name: &str,
input: &Value,
) -> Result<(), LogError>
pub fn start_saga( &self, saga_id: u64, name: &str, input: &Value, ) -> Result<(), LogError>
Insert a fresh saga row in running state. Plain INSERT (not
OR REPLACE): a duplicate saga_id is a bug worth surfacing,
not a silent overwrite. Same rationale as srv’s start_saga
(codex P1 + reagent P1 PR #631).
Sourcepub fn terminate_saga(
&self,
saga_id: u64,
outcome: SagaOutcome,
) -> Result<(), LogError>
pub fn terminate_saga( &self, saga_id: u64, outcome: SagaOutcome, ) -> Result<(), LogError>
Write a saga’s terminal lifecycle row. Called by PR LSD-2’s
apply_action when the saga returns Done / Failed. The
recovery walker uses mark_failed_compensation instead.
Sourcepub fn start_step(
&self,
saga_id: u64,
step_index: u32,
name: &str,
target: PipeTarget,
cmd: &Command,
) -> Result<(), LogError>
pub fn start_step( &self, saga_id: u64, step_index: u32, name: &str, target: PipeTarget, cmd: &Command, ) -> Result<(), LogError>
Insert a pending step row before dispatching the command.
name is a short discriminant string (e.g. “issue_cmd_host_reap_panes”);
cmd is serialized as JSON for replay/debugging; target
records which pipe the command was destined for so --diag sagas can show provenance.
Sourcepub fn finish_step(
&self,
saga_id: u64,
step_index: u32,
output: &Event,
) -> Result<(), LogError>
pub fn finish_step( &self, saga_id: u64, step_index: u32, output: &Event, ) -> Result<(), LogError>
Mark a step succeeded and store the awaited event as JSON.
PR LSD-2 calls this from route_event_to_sagas when a saga’s
on_event consumes its awaited bus event.
Sourcepub fn fail_step(
&self,
saga_id: u64,
step_index: u32,
reason: &str,
) -> Result<(), LogError>
pub fn fail_step( &self, saga_id: u64, step_index: u32, reason: &str, ) -> Result<(), LogError>
Mark a step failed. Stores the reason in the step’s
failure_reason column (distinct from srv’s log, which
stuffs the reason into output_json as {"error": ...};
LSD schema gives us a dedicated column so we use it).
Sourcepub fn unresolved_sagas(&self) -> Result<Vec<UnresolvedLauncherSaga>, LogError>
pub fn unresolved_sagas(&self) -> Result<Vec<UnresolvedLauncherSaga>, LogError>
Return all sagas still in running, compensating, or
failed state, each with its full step list. PR LSD-3’s
startup recovery walker iterates this list and calls
mark_failed_compensation on each (LSD spec §3.5).
failed is included for symmetry with srv’s unresolved_sagas
(codex P1 PR #631 round 2): a launcher saga marked failed
without restart-time recovery would still benefit from the
failed_compensation upgrade so --diag sagas consistently
surfaces it as “needs operator attention.”
Sourcepub fn get_saga_steps(
&self,
saga_id: u64,
) -> Result<Vec<UnresolvedLauncherStep>, LogError>
pub fn get_saga_steps( &self, saga_id: u64, ) -> Result<Vec<UnresolvedLauncherStep>, LogError>
Fetch the step rows for a single saga regardless of saga state.
unresolved_sagas filters out failed_compensation (and other
terminal states), but --diag sagas needs to surface step rows
for sagas the recovery walker just marked failed_compensation
— operators triaging a recovered crash need to see what was
pending when the launcher exited. (codex P1 PR #647 round 1.)
Sourcepub fn mark_failed_compensation(
&self,
saga_id: u64,
reason: &str,
) -> Result<(), LogError>
pub fn mark_failed_compensation( &self, saga_id: u64, reason: &str, ) -> Result<(), LogError>
Mark a saga as failed_compensation — the recovery walker’s
terminal write. Idempotent across repeated calls (the saga
stays in failed_compensation; ended_at is rewritten to
the latest call’s timestamp; failure_reason is preserved
when already populated and the new reason is APPENDED rather
than overwritten — see SQL CASE WHEN below). This preserves
the original failure cause (e.g. timeout) while adding the
recovery context. (codex P2 PR #647 round 1: post-mortem
preservation.) LSD spec §3.5 — operator-review terminal state.
Sourcepub fn snapshot_recent(
&self,
limit: usize,
) -> Result<Vec<SagaSummary>, LogError>
pub fn snapshot_recent( &self, limit: usize, ) -> Result<Vec<SagaSummary>, LogError>
Return up to limit recent sagas for --diag sagas. Sorted
most-recent-first by COALESCE(ended_at, started_at). Mirrors
srv’s snapshot_recent shape.
Sourcepub fn vacuum_older_than(
&self,
cutoff: DateTime<Utc>,
) -> Result<usize, LogError>
pub fn vacuum_older_than( &self, cutoff: DateTime<Utc>, ) -> Result<usize, LogError>
Delete saga rows whose ended_at is before cutoff AND whose
state is terminal (completed, failed, failed_compensation).
Returns the number of rows deleted. In-flight sagas (running,
compensating) are NEVER vacuumed — that would mask
crashed-mid-saga incidents from the recovery walker (LSD spec §3.6).
ON DELETE CASCADE on launcher_saga_step.saga_id ensures
the corresponding step rows go with the saga in a single
SQLite transaction — no manual cleanup needed.