Skip to content

feat: make file writes survive interruption, permissions and antivirus #598

Description

@InstaZDLL

Not to be confused with #590. That one makes tag writes fast; this one makes them survive what can go wrong. Both are prerequisites for batch tag work, for different reasons.

What is missing

No sync_all() before the rename. The atomic write pattern is write-temp, then rename. Without an explicit flush before that rename, a power loss or a crash can leave the rename committed over a temp file whose contents never reached the platter — a file that is neither the old one nor the new one.

Permissions are not carried across. A rewritten file gets whatever the process default gives it, so a file that was read-only, or group-writable, or carried an ACL somebody set on purpose, quietly changes character on the way through.

The Windows read-only attribute is a hard stop. A file marked read-only cannot be replaced, and the operation fails with an error that describes the symptom rather than the cause. Lifting it for the write and putting it back is a few lines, and it is the difference between "cannot save" and saving.

Antivirus holds files open, briefly. On Windows, a freshly written file is frequently scanned before the process can rename over it, and the rename fails with a sharing violation that a retry a moment later would have avoided. One attempt turns a transient lock into a permanent failure the user sees as data loss.

Why it comes before the batch work

Each of these is survivable once and unacceptable three hundred times. A single failed save is an annoyance somebody retries; the same failure rate applied to a folder-wide operation means every batch ends with a handful of files in an unknown state and no way to tell which.

It is also the stated prerequisite for online tag retrieval, which writes across a whole album at once.

Traps

  • Pause playback before rewriting the current track's file on Windows, and re-hash blake3 into track.file_hash afterwards (invariant).
  • track.file_hash carries two different algorithms — head-and-tail from the scanner, whole-file from the tag editor. Whichever path writes keeps its own convention.
  • A retry loop needs a ceiling and a distinction. Retrying a sharing violation is right; retrying a permission error is a hang.
  • Cross-volume moves are copy, verify, then delete — never delete-then-copy, and never a rename that silently degrades to a copy without the verify.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestplannedPlanned for a future releasescope: backendRust/Tauri backend (src-tauri/)type: featNew feature

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions