Batch track removal that guarantees the database matches the disk #4
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
wokoman/ironpod#4
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
A single batch-removal entry point that owns the rule every caller currently re-implements: the database on disk always matches the audio files on disk.
Removing tracks is a loop of two steps per track — drop it from the in-memory database, then delete its audio file — followed by one write of the database at the end. Getting the failure behaviour right is not obvious, and today three call sites each guess at it separately. One of them guesses wrong (see #2). This ticket makes the guarantee a property of the module instead of something each caller has to remember.
Nothing changes for users yet. The existing single-track removal stays public and callers stay on it, so the tree stays green; the migration is #5.
The settled interface
From the design session — this shape encodes decisions, so it is worth pinning precisely:
Three points behind that shape:
Stop at the first failure. Deliberately unlike the copy direction, which presses on. A failed copy is per-file; a failed delete is usually systemic — the volume vanished, the filesystem went read-only — and pressing on turns one stranded file into two hundred.
Write the database only when at least one removal succeeded. This is a correctness rule, not an optimisation, and it needs a comment saying so or someone will delete it as dead weight. A track is dropped from the database before its file is deleted, so if the very first deletion fails the database has already changed while the file is still there. Writing then would manufacture a stranded file out of a run that achieved nothing; not writing leaves disk and database agreeing.
The progress callback fires before each removal, not after. The browser is single-threaded and has to repaint before it blocks. This is the opposite of the copy direction's callback, which reports results after the fact, so it must not be named as though they are the same thing.
RemoveFailedneeds a hand-writtenDisplay/Errorrather than a derive:anyhow::Errordoes not implementstd::error::Error, so it cannot be a derived error source.Acceptance criteria
# Errorssection stating the stopping rule, the write guarantee and that a write renumbers track IDs so callers must re-readcargo clippy --all-targetsclean; tests pass with no device attachedBlocked by