pub(super) const DDL: &str = "
CREATE TABLE IF NOT EXISTS launcher_saga (
saga_id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
state TEXT NOT NULL CHECK (state IN ('running', 'completed', 'failed', 'compensating', 'failed_compensation')),
started_at TEXT NOT NULL,
ended_at TEXT,
input_json TEXT NOT NULL,
failure_reason TEXT
);
CREATE TABLE IF NOT EXISTS launcher_saga_step (
saga_id INTEGER NOT NULL REFERENCES launcher_saga(saga_id) ON DELETE CASCADE,
step_index INTEGER NOT NULL,
name TEXT NOT NULL,
state TEXT NOT NULL CHECK (state IN ('pending', 'succeeded', 'failed', 'compensated')),
cmd_json TEXT,
target TEXT,
started_at TEXT NOT NULL,
ended_at TEXT,
output_json TEXT,
failure_reason TEXT,
PRIMARY KEY (saga_id, step_index)
);
CREATE INDEX IF NOT EXISTS idx_launcher_saga_state
ON launcher_saga(state);
CREATE INDEX IF NOT EXISTS idx_launcher_saga_step_state
ON launcher_saga_step(saga_id, state);
";Expand description
DDL applied on every LauncherSagaLog::open(). Idempotent:
CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS make
reopening the same DB a no-op. Schema mirrors LSD spec §3.2 verbatim
(timestamps as RFC3339 TEXT — easier to grep in SQLite shells than
epoch ms; PR LSD-2’s coordinator wiring serializes via
chrono::DateTime<Utc>::to_rfc3339).