Skip to content

feat(storage): move runtime state to SQLite - #173

Merged
owainlewis merged 1 commit into
mainfrom
codex/170-sqlite-state
Jul 30, 2026
Merged

feat(storage): move runtime state to SQLite#173
owainlewis merged 1 commit into
mainfrom
codex/170-sqlite-state

Conversation

@owainlewis

@owainlewis owainlewis commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

Moves channel cursors and channel-qualified backend session mappings into the canonical push.db SQLite database. Existing state.json files migrate once through an atomic, idempotent transaction, remain untouched as a recovery copy, and continue to honor explicit state_path, legacy last_row_id, and unqualified iMessage session keys.

The merged PushPaths owner now supplies both the canonical database and legacy migration paths to the state store. Explicit state_path and database_path overrides remain compatible. The Slack durable inbox remains separate on PushPaths.inbox because its acknowledgement-queue lifecycle differs from canonical runtime state. Database and migration errors fail closed before polling or pause processing with actionable context.

Why

Whole-file JSON rewrites created a second mutable source of truth and could not provide database-level concurrency guarantees. SQLite now provides monotonic cursor upserts, transactional session rotation, and crash-safe migration markers under the repository's canonical runtime-path owner.

Test plan

Verified after rebasing onto current main (795f326, including PRs #171, #172, and #175):

  • cargo fmt --all -- --check
  • cargo clippy --locked --all-targets -- -D warnings
  • cargo build --locked
  • cargo test --locked (368 unit, 2 docs, 14 CLI integration, 3 crash tests)
  • python -m mkdocs build --strict
  • Fresh independent review of exact commit 11fb11d: approved with no blocker or important finding

Risks

The main risk is upgrade migration behavior. Tests cover legacy iMessage keys, explicit and fallback iMessage cursors, multiple channels and backends, empty session IDs, migration interruption and repetition, corrupt JSON, database-open failure, concurrent cursor writes, backend changes, exact channel-qualified /clear rotation, and runtime path overrides. The retained legacy JSON is intentionally not deleted or rewritten after migration.

Related issue

Closes #170

@owainlewis
owainlewis force-pushed the codex/170-sqlite-state branch from 80bd7b9 to 11fb11d Compare July 30, 2026 13:39
@owainlewis
owainlewis marked this pull request as ready for review July 30, 2026 13:42
@owainlewis
owainlewis merged commit 3911f1b into main Jul 30, 2026
3 checks passed
@owainlewis
owainlewis deleted the codex/170-sqlite-state branch July 30, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move cursor and backend session state into SQLite

1 participant