mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-04 23:12:27 +02:00
`finalize_http_transfer` links the staged `.partial` to its final path
and then removes the partial. Linking is the one step that is not
naturally repeatable: `hard_link` answers `AlreadyExists`.
A crash between those two steps leaves both files. The task was not yet
marked Completed -- that happens after finalization -- so it is requeued
on restart, resumes, finds the partial already complete, takes the
`Unsatisfiable { complete: true }` branch, and finalizes again. That
second call returned `AlreadyExists`, which the caller turns into
`Failed`. A recording whose bytes are entirely and correctly on disk was
reported as failed, and because retry re-runs the same path it failed
that way every time.
Finalization is now idempotent. An existing file at the final path is
this task's own earlier link -- path reservation gives it sole claim --
so the transfer completes. If the sizes disagree that reasoning does not
hold, and it errors loudly instead of publishing bytes nothing checked.
The signature narrows from `&RecordingTask` to the two paths it actually
used, which is what makes the behaviour testable at all.
Also pins a claim I made and had wrong: retention keys on
(owner, channel), so two users sharing one file are already in separate
groups and each keeps their own entry under keep_last_per_channel. There
was nothing to fix; there is now a test saying so.