3.9 KiB
3.9 KiB
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.
- T1 — fsdy instance parameterization.
Client::new(provider_root, disk_root)with validation; replace every hardcoded"/fs"/"/fs/"insideClientmethods with instance state (disk_path,is_track_path,list_dirtitle/paths,get_lib_root);initbuilds the/fsinstance vianew. 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). - 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). - T3 — QueueStore.
open(create_dir_all),validate_name,save/persist_currentvia one tmp-and-swap writer (entries +.queue-state.tomlsidecar),load_current(sorted listing, skip broken, default state on sidecar defects). Verifies: allqueue_store::testsexceptpersister_writes_the_latest_snapshot; gates "Queue store". - 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). - T5 — playback loop wiring.
Playback::newtakesOption<Arc<QueueStore>>; watch sender + persist sends frombroadcast_queue,play, and the shuffle/repeat toggles;runspawns the persister;PlaybackCommand::SaveQueue { name, result_tx }handled on the loop (snapshot, spawn write, reply);restore_currentapplies tracks + position + mods beforerun, no autoplay. Playback-level tests (restore → Init snapshot; SaveQueue ok/empty; a queue mutation reaches the store). Verifies: newplayback::tests; gates "Playback wiring". - T6 — orchestrator + server startup.
queues_client: Option<Arc<fsdy::Client>>mounted overQueueStore::dirat/queues; routing arms in every trait method; root child when present;main.rsbuilds the store (non-fatal), restores, spawns everything in order. Verifies: gates "RPC and orchestrator"; workspace build. - T7 — rpc
save_queue. SendSaveQueueto the playback loop, mapSaveQueueError→Status(invalid_argument / failed_precondition / internal). Verifies: gate "RPC and orchestrator" (error mapping). - 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: newcbd-tuitests; gates "TUI". - T9 — full verification. Whole workspace suite green;
clippy/fmt/taplo/markdownlint clean; walk every gate in
quality/queue-persistence.mdand tick it; notodo!()left. - T10 — live smoke test. Temp store + real tree: persist a mixed
queue (tidal + fs tracks), reload it, browse
/queuesthrough 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. - T11 — docs.
plan/summary.mdsection incl. deviations; reconcilearchitecture/fs-provider.md(one-hop links) andarchitecture/queue-persistence.mdif the implementation diverged.