69 lines
3.9 KiB
Markdown
69 lines
3.9 KiB
Markdown
# Plan: queue-persistence
|
|
|
|
Ordered tasks; each names its verification (tests in `fsdy/src/lib.rs` /
|
|
`crabidy-server/src/queue_store.rs` and/or gates in
|
|
`quality/queue-persistence.md`). Stubs and workspace wiring exist; the new
|
|
fsdy/queue-store tests fail on `todo!()` at plan time.
|
|
|
|
- [x] **T1 — fsdy instance parameterization.** `Client::new(provider_root,
|
|
disk_root)` with validation; replace every hardcoded `"/fs"`/`"/fs/"`
|
|
inside `Client` methods with instance state (`disk_path`,
|
|
`is_track_path`, `list_dir` title/paths, `get_lib_root`); `init` builds
|
|
the `/fs` instance via `new`. Verifies:
|
|
`instances_serve_their_own_provider_root`,
|
|
`instance_paths_cannot_escape_their_root_either`,
|
|
`new_rejects_malformed_roots`; gates "fsdy instances" (prefix
|
|
derivation, single traversal site).
|
|
- [x] **T2 — fsdy serialization.** `TrackFile::from_track` (uniform link
|
|
playable), `to_toml`, `track_file_name` (zero-padded prefix +
|
|
sanitized title). Verifies: `from_track_round_trips_through_a_link_file`,
|
|
`from_track_serializes_sparse_metadata`,
|
|
`track_file_names_sort_in_queue_order_and_stay_plain`,
|
|
`links_into_fs_instances_are_legal_and_one_hop` (rule relaxation, done
|
|
at stub time).
|
|
- [x] **T3 — QueueStore.** `open` (create_dir_all), `validate_name`,
|
|
`save`/`persist_current` via one tmp-and-swap writer (entries +
|
|
`.queue-state.toml` sidecar), `load_current` (sorted listing, skip
|
|
broken, default state on sidecar defects). Verifies: all
|
|
`queue_store::tests` except `persister_writes_the_latest_snapshot`;
|
|
gates "Queue store".
|
|
- [x] **T4 — persister task.** `spawn_persister`: watch changes →
|
|
debounce → skip-if-equal → `persist_current`, warn on failure, exit on
|
|
sender drop. Verifies: `persister_writes_the_latest_snapshot`; gates
|
|
"playback wiring" (debounce/skip, warnings only).
|
|
- [x] **T5 — playback loop wiring.** `Playback::new` takes
|
|
`Option<Arc<QueueStore>>`; watch sender + persist sends from
|
|
`broadcast_queue`, `play`, and the shuffle/repeat toggles; `run`
|
|
spawns the persister; `PlaybackCommand::SaveQueue { name, result_tx }`
|
|
handled on the loop (snapshot, spawn write, reply);
|
|
`restore_current` applies tracks + position + mods before `run`, no
|
|
autoplay. Playback-level tests (restore → Init snapshot; SaveQueue
|
|
ok/empty; a queue mutation reaches the store). Verifies: new
|
|
`playback::tests`; gates "Playback wiring".
|
|
- [x] **T6 — orchestrator + server startup.** `queues_client:
|
|
Option<Arc<fsdy::Client>>` mounted over `QueueStore::dir` at
|
|
`/queues`; routing arms in every trait method; root child when
|
|
present; `main.rs` builds the store (non-fatal), restores, spawns
|
|
everything in order. Verifies: gates "RPC and orchestrator";
|
|
workspace build.
|
|
- [x] **T7 — rpc `save_queue`.** Send `SaveQueue` to the playback loop,
|
|
map `SaveQueueError` → `Status` (invalid_argument /
|
|
failed_precondition / internal). Verifies: gate "RPC and
|
|
orchestrator" (error mapping).
|
|
- [x] **T8 — TUI save flow.** `Action::QueueSaveAs` (`w`, `Scope::Queue`),
|
|
`InputPurpose::SaveQueue` (+ overlay label), `MessageFromUi::SaveQueue`,
|
|
orchestrator arm → `rpc::save_queue`. TUI tests: binding lookup,
|
|
overlay open only with a non-empty queue, submit sends the trimmed
|
|
name. Verifies: new `cbd-tui` tests; gates "TUI".
|
|
- [x] **T9 — full verification.** Whole workspace suite green;
|
|
clippy/fmt/taplo/markdownlint clean; walk every gate in
|
|
`quality/queue-persistence.md` and tick it; no `todo!()` left.
|
|
- [x] **T10 — live smoke test.** Temp store + real tree: persist a mixed
|
|
queue (tidal + fs tracks), reload it, browse `/queues` through the
|
|
provider instance, queue a saved folder via the resolve walk — remove
|
|
any temporary probe afterwards. Verifies: end-to-end D2/D5 behavior
|
|
outside unit scope.
|
|
- [x] **T11 — docs.** `plan/summary.md` section incl. deviations;
|
|
reconcile `architecture/fs-provider.md` (one-hop links) and
|
|
`architecture/queue-persistence.md` if the implementation diverged.
|