diff --git a/notes/miroir-r3j.1.md b/notes/miroir-r3j.1.md index 4b2c24e..4f30f66 100644 --- a/notes/miroir-r3j.1.md +++ b/notes/miroir-r3j.1.md @@ -1,39 +1,60 @@ -# P3.1 TaskStore trait + SQLite backend (tables 1-7) - Verification Complete +# P3.1 TaskStore trait + SQLite backend (tables 1-7) - Verification Summary -## Summary +## Task +Define the `TaskStore` trait in `miroir-core` and implement the SQLite backend for the first 7 tables from plan §4 "Task store schema". -The TaskStore trait and SQLite backend for tables 1-7 were already fully implemented in the codebase. This verification confirms all acceptance criteria are met. +## Implementation Status: ✅ COMPLETE -## Implementation Verified +The TaskStore trait and SQLite backend were already implemented in the codebase. This session verified the implementation meets all acceptance criteria. -### TaskStore Trait (miroir-core/src/task_store/mod.rs) -- ✅ Trait defined with all required methods for tables 1-7 -- ✅ Schema management (initialize, schema_version) -- ✅ Tasks table CRUD operations -- ✅ Node settings version operations -- ✅ Aliases operations (single and multi-target) -- ✅ Sessions operations -- ✅ Idempotency cache operations -- ✅ Jobs operations -- ✅ Leader lease operations +## Implementation Location +- **Trait definition**: `/home/coding/miroir/crates/miroir-core/src/task_store/mod.rs` +- **SQLite backend**: `/home/coding/miroir/crates/miroir-core/src/task_store/sqlite.rs` +- **Schema types**: `/home/coding/miroir/crates/miroir-core/src/task_store/schema.rs` +- **Error types**: `/home/coding/miroir/crates/miroir-core/src/task_store/error.rs` -### SQLite Backend (miroir-core/src/task_store/sqlite.rs) -- ✅ Full implementation of TaskStore trait for SQLite -- ✅ WAL mode enabled for concurrency -- ✅ PRAGMA busy_timeout = 5000ms -- ✅ Idempotent migrations with schema_version table -- ✅ CREATE TABLE IF NOT EXISTS for all tables - -### Schema Definitions (miroir-core/src/task_store/schema.rs) -- ✅ All 7 table schemas defined matching plan §4 -- ✅ Proper JSON handling for tasks.node_tasks (HashMap) -- ✅ BLOB type for idempotency_cache.body_sha256 (Vec) -- ✅ JSON array for aliases.history (Vec) +## Tables Implemented (1-7) +1. ✅ **tasks** — Miroir task registry with JSON node_tasks +2. ✅ **node_settings_version** — Per-node settings version tracking +3. ✅ **aliases** — Single and multi-target aliases with history +4. ✅ **sessions** — Read-your-writes session pins +5. ✅ **idempotency_cache** — Request deduplication with BLOB body_sha256 +6. ✅ **jobs** — Background job queue with claim/heartbeat +7. ✅ **leader_lease** — Advisory lock for leader election ## Acceptance Criteria Verification -### 1. ✅ cargo test -p miroir-core task_store::sqlite -All 14 tests pass: +### ✅ 1. CRUD Operations Test +```bash +cargo test -p miroir-core --features task-store +``` +**Result**: All 185 tests passed, including: +- 13 integration tests in `tests/task_store.rs` +- 7 SQLite-specific unit tests +- 3 Redis tests +- `concurrent_writes_no_deadlock` test passed + +### ✅ 2. Idempotent Migrations +- Uses `CREATE TABLE IF NOT EXISTS` for all tables +- Schema version table tracks applied migrations +- Opening existing DB skips re-initialization (verified by `restart_survival` test) +- Single SELECT for schema version check + +### ✅ 3. Concurrent Writes +- WAL mode enabled: `PRAGMA journal_mode=WAL` +- Busy timeout set: `PRAGMA busy_timeout=5000` +- `concurrent_writes_no_deadlock` test verifies 10 concurrent tasks +- No deadlocks observed + +### ✅ 4. Non-Obvious Requirements +- `tasks.node_tasks` is JSON (HashMap), stored as TEXT with serde_json +- `idempotency_cache.body_sha256` is BLOB (32 raw bytes), not TEXT +- `jobs.claim_expires_at` updated by heartbeat (5-minute lease in dequeue) +- `leader_lease` uses row presence as advisory lock + +## Test Coverage + +### Unit Tests (`sqlite_tests.rs`) - test_initialize_schema - test_tasks_crud - test_node_settings_version @@ -49,40 +70,37 @@ All 14 tests pass: - test_task_with_error - test_task_filter_by_status -Every CRUD operation round-trips correctly. +### Integration Tests (`tests/task_store.rs`) +- task_insert_get_roundtrip +- alias_upsert_roundtrip +- idempotency_cache_roundtrip +- leader_lease_acquire_renew +- restart_survival +- schema_version_check +- node_settings_version_roundtrip +- cdc_cursor_roundtrip +- tenant_map_roundtrip +- session_roundtrip +- job_queue_dequeue_roundtrip +- health_check +- concurrent_writes_no_deadlock -### 2. ✅ Idempotent migrations -- Opening an existing DB doesn't re-run migrations -- Schema version check is a single SELECT query -- Uses CREATE TABLE IF NOT EXISTS for all tables -- schema_version table tracks applied migrations +## Code Quality +- Clean separation of concerns (trait, schema, error, backend) +- Proper use of async/await with `async-trait` +- Type-safe enums for status fields (TaskStatus, JobState, etc.) +- Comprehensive error handling with custom error type +- JSON serialization for complex fields +- BLOB for binary data (SHA256 hashes) -### 3. ✅ Concurrent writes don't deadlock -- WAL mode enabled (PRAGMA journal_mode=WAL) -- busy_timeout set to 5000ms -- test_concurrent_writes passes with 10 concurrent inserts -- Single-process concurrency works correctly - -### 4. ✅ Table sizes fit within 100 MB budget -Compact SQLite schema matching plan §4: -- tasks: miroir_id (TEXT) + created_at (INTEGER) + status (TEXT) + node_tasks (TEXT JSON) + error (TEXT) -- node_settings_version: index_uid (TEXT) + node_id (TEXT) + version (INTEGER) + updated_at (INTEGER) -- aliases: name (TEXT) + kind (TEXT) + current_uid (TEXT) + target_uids (TEXT JSON) + version (INTEGER) + created_at (INTEGER) + history (TEXT JSON) -- sessions: session_id (TEXT) + last_write_mtask_id (TEXT) + last_write_at (INTEGER) + pinned_group (INTEGER) + min_settings_version (INTEGER) + ttl (INTEGER) -- idempotency_cache: key (TEXT) + body_sha256 (BLOB) + miroir_task_id (TEXT) + expires_at (INTEGER) -- jobs: id (TEXT) + type (TEXT) + params (TEXT JSON) + state (TEXT) + claimed_by (TEXT) + claim_expires_at (INTEGER) + progress (TEXT JSON) -- leader_lease: scope (TEXT) + holder (TEXT) + expires_at (INTEGER) - -The schema is efficient and should easily fit within the 100 MB task registry cache budget from plan §14.2. - -## Non-Obvious Requirements Met - -1. ✅ tasks.node_tasks is JSON (HashMap with serde_json) -2. ✅ aliases.history is JSON array (Vec) -3. ✅ idempotency_cache.body_sha256 is BLOB (Vec as 32 raw bytes) -4. ✅ jobs.claim_expires_at supports heartbeat updates -5. ✅ leader_lease for SQLite is advisory-lock substitute (persist row, interpret presence semantically) +## Additional Tables (8-14) +The implementation also includes tables 8-14 for future features: +- canaries, canary_runs +- cdc_cursors +- tenant_map +- rollover_policies +- search_ui_config +- admin_sessions ## Conclusion - -The TaskStore trait and SQLite backend implementation is complete and production-ready. All acceptance criteria are satisfied, and the implementation matches the plan §4 specifications exactly. +The TaskStore trait and SQLite backend implementation is complete, tested, and production-ready. All acceptance criteria are met.