fix(engine): cross-backend integrity guard with retry-then-damaged
A truncated debrid download (in-memory byte counter hit 100% while the
NFS write-back silently dropped most of the bytes) was marked completed.
The 1.1.6 fsync fix closed the debrid-specific hole; this generalizes the
guarantee so "completed" never means a corrupt file on ANY backend.
- IntegrityError + bounded retry: on a corrupt/short result the manager
re-downloads the same source up to 3x (clean start), then surfaces the
task as damaged ("corrupt download:" prefix) instead of completing it.
- verify (size mismatch / empty), debrid (incomplete / post-write / flush),
torrent (BytesMissing), usenet (par2 unrepairable / repair-failed) all
classify integrity failures so they route through the retry/damaged path.
- scanner: a file ffprobe can't read is emitted as a damaged library_item
(reason "unreadable") instead of being silently dropped from the sync.
- tests: manager retry-then-success + retry-exhausted-then-damaged,
verifying->resolving transition, damaged sync item.
This commit is contained in:
parent
271413e0f9
commit
a5f3f0914a
13 changed files with 400 additions and 91 deletions
|
|
@ -14,6 +14,13 @@ import (
|
|||
// be checked is delivered UNVERIFIED, not verified.
|
||||
var ErrPar2NotInstalled = errors.New("par2 not installed")
|
||||
|
||||
// ErrPar2Unrepairable is returned by Par2Verify when parity confirms the data is
|
||||
// damaged AND par2 reports repair is not possible — the file is definitively
|
||||
// corrupt (distinct from a transient par2 probe error). The pipeline marks the
|
||||
// delivery Corrupt so the engine treats it as an integrity failure and
|
||||
// re-downloads, rather than shipping a broken file with a soft warning.
|
||||
var ErrPar2Unrepairable = errors.New("par2: verification failed and repair not possible")
|
||||
|
||||
// par2Lookup probes whether the par2 binary is on PATH. It's a package var so
|
||||
// tests can simulate a missing binary without touching the real PATH.
|
||||
var par2Lookup = func() bool {
|
||||
|
|
@ -42,7 +49,7 @@ func Par2Verify(par2File string) error {
|
|||
return &Par2RepairableError{Par2File: par2File}
|
||||
}
|
||||
if strings.Contains(outStr, "Repair is not possible") {
|
||||
return fmt.Errorf("par2: verification failed and repair not possible:\n%s", outStr)
|
||||
return fmt.Errorf("%w:\n%s", ErrPar2Unrepairable, outStr)
|
||||
}
|
||||
return fmt.Errorf("par2 verify: %w\n%s", err, outStr)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue