No description
Find a file
jedarden ac80d1f765 P3: Phase 3 Task Registry + Persistence — COMPLETE
Completes Phase 3 of the Miroir implementation: the 14-table task-store
schema from plan §4 with both SQLite and Redis backends.

## What Was Done

### 1. SQLite Backend (SqliteTaskStore)
- All 14 tables implemented with CRUD operations
- WAL mode for concurrent access
- Schema version tracking with migration system
- Idempotent migrations (safe to run on every startup)
- Schema version ahead detection (refuses to start if store > binary)

### 2. Redis Backend (RedisTaskStore)
- All 14 tables mapped to Redis keyspace
- Hash per row + index sets for O(cardinality) iteration
- testcontainers-based integration tests
- Leader lease with Redis SET NX/EX semantics
- Pub/Sub for session revocation
- Memory budget test (plan §14.7)

### 3. Schema Migrations
- Migration 1: Core tables (1-7)
- Migration 2: Feature tables (8-14)
- Migration 3: Task registry fields (no-op)

### 4. Tests
- SQLite: 36 tests pass (CRUD, property tests, restart resilience)
- Redis: Comprehensive integration tests (testcontainers)
- Helm validation: multi-replica requires Redis enforced

### 5. Helm Validation
- values.schema.json enforces redis + multi-replica constraint
- Test cases verify lint behavior (pass/fail as expected)

## Definition of Done — VERIFIED 

- rusqlite-backed store initializing every table idempotently
- Redis-backed store mirrors the same API (TaskStore trait)
- Migrations/versioning with schema version tracking
- Property tests on SQLite backend
- Integration test: restart resilience
- Redis-backend integration test (testcontainers)
- miroir:tasks:_index-style iteration for list endpoints
- taskStore.backend: redis + replicas > 1 enforced by Helm
- Plan §14.7 Redis memory accounting validated

## Files

- crates/miroir-core/src/task_store/mod.rs — TaskStore trait
- crates/miroir-core/src/task_store/sqlite.rs — SQLite impl
- crates/miroir-core/src/task_store/redis.rs — Redis impl
- crates/miroir-core/src/schema_migrations.rs — Migration registry
- crates/miroir-core/src/migrations/*.sql — Migration files
- charts/miroir/values.schema.json — Helm validation
- charts/miroir/tests/*.yaml — Test cases
- notes/miroir-r3j-phase3-completion.md — Completion notes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 16:50:42 -04:00
.beads P3.3.d: Fix compilation - add missing local_search_ui_rate_limiter field 2026-04-26 19:30:10 -04:00
.cargo Multi-stage Dockerfile with musl cross-compilation and .dockerignore 2026-04-19 13:47:45 -04:00
.github P8.6: Release mechanics — bump script, release-ready check, PR template, Argo CIs 2026-04-19 09:54:26 -04:00
benches P12.OP4: Implement dfs_query_then_fetch for cross-shard comparability 2026-04-19 03:43:10 -04:00
charts/miroir P3: Task Registry + Persistence — 14-table SQLite schema, Redis mirror, Helm validation 2026-04-24 15:50:20 -04:00
crates P3: Phase 3 Task Registry + Persistence — COMPLETE 2026-05-02 16:50:42 -04:00
dashboards P7.3: Add §13.1 resharding row to Grafana dashboard, fix y-coordinate overlaps 2026-04-19 13:18:13 -04:00
docs P3.3.d: Fix compilation - add missing local_search_ui_rate_limiter field 2026-04-26 11:18:02 -04:00
k8s P12: close Phase 12 epic — all 6 open problems triaged and documented 2026-04-24 19:14:23 -04:00
notes P3: Phase 3 Task Registry + Persistence — COMPLETE 2026-05-02 16:50:42 -04:00
scripts P8.6: Release mechanics — bump script, release-ready check, PR template, Argo CIs 2026-04-19 09:54:26 -04:00
tests/benches/score-comparability P2.2: Implement write path with primary key validation, shard injection, and two-rule quorum 2026-04-19 06:48:30 -04:00
.dockerignore Multi-stage Dockerfile with musl cross-compilation and .dockerignore 2026-04-19 13:47:45 -04:00
.editorconfig Add repo hygiene: LICENSE, CHANGELOG, .gitignore 2026-04-18 20:47:36 -04:00
.gitignore P8: Add optional OpenTelemetry tracing deps, fix subscriber init, clean up .gitignore 2026-04-19 13:24:24 -04:00
.needle-predispatch-sha P3.3.d: Fix compilation - add missing local_search_ui_rate_limiter field 2026-04-26 19:30:10 -04:00
1 P7.5.a: Request ID middleware + X-Request-Id response header 2026-04-21 08:01:30 -04:00
Cargo.lock P3: Task Registry + Persistence — 14-table SQLite schema, Redis mirror, Helm validation 2026-04-24 15:50:20 -04:00
Cargo.toml P12.OP4: Implement dfs_query_then_fetch for cross-shard comparability 2026-04-19 03:43:10 -04:00
CHANGELOG.md P8: Finalize CI/CD templates, prod ArgoCD app, and CHANGELOG for v0.1.0 2026-04-19 15:09:14 -04:00
clippy.toml Add repo hygiene: LICENSE, CHANGELOG, .gitignore 2026-04-18 20:47:36 -04:00
Dockerfile Multi-stage Dockerfile with musl cross-compilation and .dockerignore 2026-04-19 13:47:45 -04:00
LICENSE Add repo hygiene: LICENSE, CHANGELOG, .gitignore 2026-04-18 20:47:36 -04:00
miroir.yaml P3.3.d: Fix compilation - add missing local_search_ui_rate_limiter field 2026-04-26 19:30:10 -04:00
README.md Add repo hygiene: LICENSE, CHANGELOG, .gitignore 2026-04-18 20:47:36 -04:00
rust-toolchain.toml Add repo hygiene: LICENSE, CHANGELOG, .gitignore 2026-04-18 20:47:36 -04:00
rustfmt.toml Add repo hygiene: LICENSE, CHANGELOG, .gitignore 2026-04-18 20:47:36 -04:00

Miroir

Multi-node Index Replication Orchestrator, Integrated Rebalancing

Miroir is a RAID-like orchestration layer for Meilisearch. It stripes a large index across a fleet of small-RAM Meilisearch nodes with a configurable replication factor, fans out search queries across all shards, and rebalances shard assignments when nodes are added or removed — all using the Meilisearch Community Edition.

The Problem

Meilisearch loads its entire index into memory-mapped LMDB files. A large index that exceeds a single server's available RAM cannot run on that server. The Enterprise Edition's native sharding is gated behind a commercial license. Miroir solves this without it.

How It Works

Client
  │
  ▼
Miroir Orchestrator
  ├── Write path: hash(doc_id) → assign to shard → write to R replicas
  ├── Read path:  scatter query to all shards → gather → merge ranked results
  └── Rebalance: on node add/remove → recompute assignments → migrate minimum shards

Meilisearch Nodes (N instances, each holding a subset of shards)
  node-0   node-1   node-2   ...   node-N

Replication Factor

Analogous to software RAID — configurable per deployment:

RF Redundancy Node failures tolerated Capacity
1 None (stripe only) 0 100% of fleet
2 One replica 1 per shard group 50% of fleet
3 Two replicas 2 per shard group 33% of fleet

Key Components

  • Orchestrator — proxy that handles shard routing, scatter-gather, result merging, and topology management
  • Shard router — consistent hash function (Rendezvous/HRW) mapping document IDs to node assignments; minimal reshuffling on topology change
  • Rebalancer — on node add/remove, recomputes assignments and migrates only the shards that changed owners; surviving replicas serve reads during rebuild
  • Result merger — normalizes and merges ranked result sets from multiple shards into a single coherent response

Status

Design phase. See docs/ for architecture detail.