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.
67 lines
2.5 KiB
Markdown
67 lines
2.5 KiB
Markdown
+++
|
|
title = "Turso cache for list performance"
|
|
priority = 3
|
|
status = "done"
|
|
ticket_type = "feature"
|
|
dependencies = []
|
|
+++
|
|
Add a Turso (libsql) 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 Turso/libsql cache avoids re-reading unchanged files by comparing file modification times (mtimes).
|
|
|
|
## Approach
|
|
|
|
### Runtime migration: async-std → tokio
|
|
|
|
libsql requires tokio. Migrate the entire crate:
|
|
|
|
- `Cargo.toml`: remove `async-std`, add `tokio = { version = "1", features = ["full"] }` and `libsql = "0.6"`
|
|
- `src/main.rs`: `#[async_std::main]` → `#[tokio::main]`, `async_std::fs::remove_file` → `tokio::fs::remove_file`
|
|
- `src/store.rs`: `use async_std::fs` → `use tokio::fs`, `use async_std::prelude::*` removed (tokio ReadDir uses `.next_entry().await` not stream iteration)
|
|
- `src/tests.rs`: `#[async_std::test]` → `#[tokio::test]`, `async_std::fs` → `tokio::fs`
|
|
|
|
### Crate dependency
|
|
|
|
```toml
|
|
tokio = { version = "1", features = ["full"] }
|
|
libsql = "0.6"
|
|
```
|
|
|
|
### store.rs additions
|
|
|
|
New async function `open_cache(root: &Path) -> Result<libsql::Connection>`:
|
|
- Opens (or creates) `.nbd/cache.db` via `libsql::Builder::new_local(path).build().await?.connect()`.
|
|
- Runs 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. Scan directory for files + mtimes (using tokio::fs::read_dir + metadata).
|
|
2. Open cache DB.
|
|
3. For each file: query cache for matching (id, mtime); if hit, deserialise from cached JSON; if miss, read file, parse, upsert to DB.
|
|
4. Delete DB rows for IDs no longer on disk.
|
|
5. Return sorted by priority desc.
|
|
|
|
Fall back to `list_tickets` on any cache error.
|
|
|
|
### main.rs
|
|
|
|
`cmd_list`, `cmd_ready`, `cmd_next` use `list_tickets_cached` instead of `list_tickets`.
|
|
|
|
## Files to change
|
|
|
|
| File | Change |
|
|
|---|---|
|
|
| `Cargo.toml` | Replace async-std with tokio, add libsql |
|
|
| `src/store.rs` | async_std → tokio fs API, add cache functions |
|
|
| `src/main.rs` | async_std → tokio main/fs |
|
|
| `src/tests.rs` | async_std → tokio test/fs |
|
|
| `tests/integration.rs` | Add cache smoke test |
|
|
|
|
## Validation
|
|
|
|
```sh
|
|
cargo fmt && cargo check && cargo clippy && cargo test
|
|
cargo run -- list # should create .nbd/cache.db on first run
|
|
cargo run -- list # second run uses cache
|
|
``` |