- LICENSE: MIT (per plan §12) - CHANGELOG.md: Keep a Changelog 1.1.0 skeleton with [Unreleased] and [0.1.0] sections matching the awk extractor from plan §7 - .gitignore: Rust target/, editor junk; Cargo.lock kept in VCS Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
API Compatibility
Goal
Miroir must be a drop-in replacement for a single Meilisearch instance. A client configured to talk to a Meilisearch host should work identically when pointed at Miroir instead — no SDK changes, no query changes, no schema changes.
What This Means
- Miroir exposes the Meilisearch REST API verbatim on its inbound interface
- All request and response shapes, status codes, error formats, and headers must match the Meilisearch spec exactly
- The
X-Meili-API-Key/Authorizationheader must be accepted and forwarded (or validated at the orchestrator boundary) - Async task responses (
taskUid,GET /tasks/{uid}) must work — the orchestrator must track and reconcile task states across nodes
The Core Value Proposition
A single Meilisearch instance is limited by the RAM of one server. Miroir removes that ceiling:
- The logical index can be arbitrarily large — sharded across N nodes, each holding a fraction
- Replication factor is tunable: RF=1 for maximum capacity, RF=2+ for resilience and read throughput
- Adding nodes expands capacity; removing nodes contracts it — the rebalancer handles redistribution
- From the client's perspective, none of this is visible
API Surface Categories
Pass-through (broadcast to all nodes):
- Index create/update/delete
- Settings (ranking rules, synonyms, stop words, filterable/sortable attributes, etc.)
- Index stats (
GET /indexes/{uid}/stats) — aggregate across nodes
Shard-routed writes:
POST /indexes/{uid}/documents— route each document by hash(primary key) to RF nodesPUT /indexes/{uid}/documents— sameDELETE /indexes/{uid}/documents/{id}— route to owning shard's RF nodesDELETE /indexes/{uid}/documentsby filter — must broadcast to all nodes
Scatter-gather reads:
POST /indexes/{uid}/search— fan out to one replica per shard, merge resultsGET /indexes/{uid}/documents— fan out, merge, paginate globallyGET /indexes/{uid}/documents/{id}— route to any replica of owning shard
Orchestrator-local:
GET /health— orchestrator health (not proxied)GET /version— return Meilisearch version of the backing nodesGET /tasks,GET /tasks/{uid}— orchestrator maintains a unified task registry
Task ID Reconciliation
Meilisearch returns a taskUid for every write operation. Nodes have independent task ID sequences. Miroir must:
- Issue writes to RF nodes
- Collect the per-node
taskUidfor each operation - Generate a Miroir task ID that maps to the set of per-node task IDs
- Return the Miroir task ID to the client
- When polled (
GET /tasks/{uid}), aggregate node task statuses — reportsucceededonly when all RF nodes reportsucceeded
Non-Goals
- Miroir does not expose any Miroir-specific management API on the Meilisearch port — topology management (add/remove nodes, rebalance) is handled out-of-band via config or a separate admin interface
- Miroir does not need to implement Meilisearch's tenant tokens or fine-grained key management — it can forward the master key to nodes and let them validate