Skip to content

fix(runtime): make local operation state transactional and durable #1092

Description

@doublewhy

Gap Claim

The local control-plane JSON store performs unlocked whole-file read/modify/write operations. Concurrent writers lose records; replacement is not file-and-directory fsynced; idempotency lookup is linear. API-404 cannot claim durable or idempotent operation state.

Existing Surface Audit

Reviewed local store serialization, audit append, state transition, idempotency lookup, control-plane execution, repository contracts, and issue #8. Adding an in-process lock would not protect multiple workers or crash consistency.

Lineage and Precedent

Implements the durable-state portion of API-404 while preserving the existing store protocol and serialized record shapes.

Literature and Practice

Use SQLite ACID transactions, WAL mode, unique constraints, foreign-key integrity, busy timeout, and explicit checkpoint/backup behavior rather than inventing a file transaction protocol.

Alternatives

  1. Thread lock around JSON: rejected because processes still race. 2. File lock plus fsync/versioning: workable but retains O(n) rewrites and complex recovery. 3. SQLite WAL with indexed constraints: chosen.

Chosen Architecture

Persist operations and audit events in normalized SQLite tables. Enforce unique idempotency keys transactionally, use compare-and-set state transitions, indexed reads, WAL and durable sync. Import legacy JSON under an exclusive migration lock, verify counts/digests, retain a timestamped backup, and switch atomically only after validation.

Documentation Defense

Document persistence guarantees, single-host scope, migration/recovery, concurrency model, backup behavior, and what is not a distributed consensus guarantee.

Verification Plan

Add thread/process lost-update tests, same-key exactly-once tests, crash/restart and interrupted migration tests, corruption diagnostics, state-transition races, audit ordering, and scale budgets.

Parent: #8

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions