kanban-persistence-json
JSON file storage backend for the kanban workspace. Implements StoreFactory and PersistenceStore from kanban-persistence.
JsonFileStore
instance_id is a random UUID generated per process; used for conflict detection.
V2 Envelope Format
V1 format was a bare Snapshot JSON object (flat, no wrapper).
Save Flow
- Check for conflict: compare file metadata (size + mtime) against the last-seen value
- Update
PersistenceMetadata(incrementsave_count, setsaved_at) - Wrap snapshot in the V2 envelope
- Write to a temporary file (
.tmpsuffix) in the same directory - Atomic rename:
temp → final path
The atomic rename means a crash at any point leaves either the old file or the new file intact — always a complete, consistent file on disk.
Debounced saving: a 500ms minimum interval is enforced between saves to avoid thrashing on rapid successive mutations.
Load Flow
- Read the file
- Detect format version: V2 envelopes begin with
{"version":2; anything else is treated as V1 - V1 migration: rename existing file to
<path>.v1.backup, parse as bareSnapshot, re-save as V2 - Parse the V2 envelope, extract and return
dataasStoreSnapshot
Conflict Detection
FileMetadata captures the file's size and modification time at last load/save. On the next save, the current file metadata is compared:
- If they match → file unchanged since last save — safe to write
- If they differ → another instance wrote the file; return
PersistenceError::Conflict
JsonStoreFactory
;
matches logic:
- If the locator ends with
.json→ true - If the locator starts with
sqlite://or ends with.sqlite/.sqlite3/.db→ false - Otherwise → true (catch-all fallback for plain file paths)
Dependencies
| Crate | Purpose |
|---|---|
kanban-persistence |
PersistenceStore, StoreFactory traits |
kanban-domain |
Snapshot type |
serde_json |
JSON parsing |
tokio |
Async I/O |
tempfile |
Temp file for atomic writes |