fix: the duplicate resolver waits for a running scan, so a copy it removes is not marked present again (#6169)
release / govulncheck (push) Successful in 13s
release / web (push) Successful in 1m25s
release / go (push) Successful in 1m38s
release / integration (push) Successful in 5m6s
release / android (push) Successful in 5m10s
release / Build signed APK (releases and dev) (push) Successful in 5m21s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 14s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 13s
release / web (push) Successful in 1m25s
release / go (push) Successful in 1m38s
release / integration (push) Successful in 5m6s
release / android (push) Successful in 5m10s
release / Build signed APK (releases and dev) (push) Successful in 5m21s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 14s
release / Verify release artifacts (tag releases only) (push) Skipped
At boot the scan lists the library, the resolver removes wrong-slot copies and marks their tracks missing, then the scan reconciles from its list and marks them present: 7 of the 13 removed on 2026-10-20 15:00 read as present with no file, and would not be wanted back until a later scan. A pass now waits while a scan younger than StuckScanThreshold is in flight and tries again a minute later; a stuck run does not hold it up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ package library
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -549,6 +551,30 @@ func TestResolveDuplicates_AgreeingLookupsDecideAnAcousticGroup_Integration(t *t
|
||||
})
|
||||
}
|
||||
|
||||
// A pass while a scan is walking the library waits for it: a copy removed
|
||||
// under the walk is marked present again when the scan reconciles. A run
|
||||
// stuck past StuckScanThreshold does not hold the resolver up.
|
||||
func TestDuplicateResolveWorker_WaitsForARunningScan_Integration(t *testing.T) {
|
||||
f := seedTrimmedAlbum(t)
|
||||
ctx := context.Background()
|
||||
w := NewDuplicateResolveWorker(f.pool, slog.New(slog.NewTextHandler(io.Discard, nil)), "", nil, ResolveSources{})
|
||||
if _, err := f.pool.Exec(ctx, `INSERT INTO scan_runs DEFAULT VALUES`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !w.tickOnce(ctx) {
|
||||
t.Error("a pass ran under a running scan")
|
||||
}
|
||||
if !exists(f.aPath) || !exists(f.bPath) {
|
||||
t.Error("a copy was removed while the scan was walking the library")
|
||||
}
|
||||
if _, err := f.pool.Exec(ctx, `UPDATE scan_runs SET started_at = now() - interval '2 hours'`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if w.tickOnce(ctx) {
|
||||
t.Error("a scan stuck for two hours held the resolver up")
|
||||
}
|
||||
}
|
||||
|
||||
// AcoustID knows the recording as no song of the album: every copy goes. With
|
||||
// AcoustID unreachable, nothing is decided and the group waits.
|
||||
func TestResolveDuplicates_TrimmedCopiesAcoustIDCannotName_Integration(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user