You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

50 lines
2.2 KiB
Markdown

+++
title = "SQLite cache for list performance"
priority = 3
status = "todo"
ticket_type = "feature"
dependencies = []
+++
Add an optional SQLite cache in `.nbd/cache.db` to accelerate `nbd list` and `nbd ready` for large ticket stores.
## Motivation
`list_tickets` currently does O(n) file reads on every call. For stores with hundreds of tickets this is measurably slow. A SQLite cache avoids re-reading unchanged files by comparing file modification times (mtimes).
## Approach
### Crate dependency
Add `sqlx` with the `sqlite` and `runtime-async-std` features to `Cargo.toml`.
### store.rs additions
New async function `open_cache(root: &Path) -> Result<sqlx::SqlitePool>`:
- Opens (or creates) `.nbd/cache.db`.
- Runs a migration: `CREATE TABLE IF NOT EXISTS tickets (id TEXT PRIMARY KEY, json TEXT NOT NULL, mtime INTEGER NOT NULL)`.
New function `list_tickets_cached(root: &Path) -> Result<Vec<Ticket>>`:
1. Open cache.
2. Read directory listing to get file names and mtimes.
3. For each file: if the DB has a row with matching mtime, use cached JSON; otherwise read file, parse, insert/update row.
4. Delete DB rows for IDs no longer on disk.
5. Return deserialized tickets sorted by priority desc.
Keep existing `list_tickets` as the non-cached fallback. Consider making `cmd_list` and `cmd_ready` use `list_tickets_cached` when available.
### Migration strategy
- The cache is always optional. If `cache.db` can't be opened, fall back to `list_tickets` (log a warning to stderr).
- The cache is never the source of truth — the JSON files are. The cache is always reconstructable by deleting `.nbd/cache.db`.
## Decision point
Decide whether to enable the cache unconditionally or gate it behind a flag (`--cache` / `NBD_CACHE=1`). Recommendation: enable by default once the feature is stable.
## Tests
- Unit test: cache hit returns same data as direct file read.
- Unit test: cache miss (mtime changed) re-reads the file.
- Unit test: deleted ticket is evicted from cache.
- Performance test (optional): benchmark 1000-ticket list with and without cache.
## Files touched
- `Cargo.toml` — add `sqlx`
- `src/store.rs``open_cache`, `list_tickets_cached`
- `src/tests.rs` — cache unit tests
- `docs/ARCHITECTURE.md` — document the cache layer