docs: library comments say what the scanner and resolver do, not how they came to be (#6277)
release / govulncheck (push) Successful in 20s
release / web (push) Successful in 1m20s
release / go (push) Successful in 1m37s
release / integration (push) Successful in 5m15s
release / android (push) Successful in 5m26s
release / Build signed APK (releases and dev) (push) Successful in 5m45s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 20s
release / web (push) Successful in 1m20s
release / go (push) Successful in 1m37s
release / integration (push) Successful in 5m15s
release / android (push) Successful in 5m26s
release / Build signed APK (releases and dev) (push) Successful in 5m45s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped
Rewrites the internal/library comment blocks to rule 32. Task, milestone, decision and rule ids are gone; the incidents behind them are restated as the constraint they left (why a file is deleted before its row, why the missing mark is a mark, why duplicates block on duration). Counts and album names from one library are dropped from production comments; test comments keep the names their fixtures use. The tagReadVersion log keeps each version's before and after, without the measurements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ import (
|
||||
syncpkg "git.fabledsword.com/bvandeusen/minstrel/internal/sync"
|
||||
)
|
||||
|
||||
// Duplicate resolver (M498 #5435, #5437; M502 #5517).
|
||||
// Duplicate resolver.
|
||||
//
|
||||
// The sweep proposes duplicate groups; the resolver decides what each one is
|
||||
// and settles the ones that are safe to settle without asking. Minstrel is the
|
||||
@@ -29,8 +29,7 @@ import (
|
||||
// - Across releases, each copy belongs to its own release (a single and its
|
||||
// album): nothing is removed, and the copies are linked as one song. An
|
||||
// album holding the song twice among them still holds it once: its extra
|
||||
// copies are merged into its best (Humanz held Saturnz Barz twice beside
|
||||
// the single, #5401).
|
||||
// copies are merged into its best.
|
||||
// - Except that a video rip is no release's copy. When every copy but one is
|
||||
// a rip, across releases or under another title, the rips are merged into
|
||||
// the one that is not.
|
||||
@@ -40,7 +39,7 @@ import (
|
||||
// lengths say which slot it belongs to, or AcoustID which song it is when
|
||||
// each copy was cut to its own slot's length, and the copies in the other
|
||||
// slots are removed so the album is fetched again (duplicate_settle.go).
|
||||
// - Anything else waits for the operator.
|
||||
// - Anything else waits for an admin.
|
||||
|
||||
const (
|
||||
// resolveMergeCap bounds the merges one pass makes. The first pass after
|
||||
@@ -50,7 +49,7 @@ const (
|
||||
// duplicateResolveTick is how often the worker runs a pass.
|
||||
duplicateResolveTick = time.Hour
|
||||
// scanWaitRetry is how soon a pass put off for a running scan is tried
|
||||
// again: a boot scan takes under a minute on the operator's library.
|
||||
// again; a boot scan is short.
|
||||
scanWaitRetry = time.Minute
|
||||
)
|
||||
|
||||
@@ -83,7 +82,7 @@ type resolveGroup struct {
|
||||
}
|
||||
|
||||
// isRip says whether a copy is a video rip: held back as one, or named like
|
||||
// one and not kept by the operator. The name is read as well as the verdict
|
||||
// one and not kept by an admin. The name is read as well as the verdict
|
||||
// because a pass reads the groups before it flags new rips.
|
||||
func isRip(m dbq.ListDuplicateGroupsForResolveRow) bool {
|
||||
if m.SourceVerdict != nil {
|
||||
@@ -141,7 +140,7 @@ type ResolveSources struct {
|
||||
Identify RecordingIdentifier
|
||||
}
|
||||
|
||||
// ResolveDuplicates runs one pass. act is the operator's auto-resolve setting;
|
||||
// ResolveDuplicates runs one pass. act is the auto-resolve setting;
|
||||
// with it off, the pass only classifies. It decides from what the library and
|
||||
// catalogue hold; ResolveDuplicatesWith may also ask MusicBrainz and AcoustID.
|
||||
func ResolveDuplicates(
|
||||
@@ -238,14 +237,13 @@ func ResolveDuplicatesWith(
|
||||
}
|
||||
|
||||
// foldAlbumCopies merges, in each cross-release group, the extra copies one
|
||||
// album holds of the song into the best of that album's copies: the one that
|
||||
// is not a video rip when only one is not, else ProposeSurvivor's choice.
|
||||
// Copies whose title or file name name different versions (versionWords) are
|
||||
// not folded: "Suite-Pee" and "Suite-Pee (Clean Version)" carried one title tag
|
||||
// on 2026-10-20, and the explicit copy went. The
|
||||
// copies on other releases stay and are linked as one song. At most budget
|
||||
// copies go. It returns how many went and the songs they were, and drops them
|
||||
// from their groups.
|
||||
// album holds of the song into the best of that album's copies: the one that is
|
||||
// not a video rip when only one is not, else ProposeSurvivor's choice. Copies
|
||||
// whose title or file name name different versions (versionWords) are not
|
||||
// folded, even when they carry one title tag: a song and its clean version are
|
||||
// both kept. The copies on other releases stay and are linked as one song. At
|
||||
// most budget copies go. It returns how many went and the songs they were, and
|
||||
// drops them from their groups.
|
||||
func foldAlbumCopies(
|
||||
ctx context.Context, pool *pgxpool.Pool, logger *slog.Logger, dataDir string,
|
||||
groups []*resolveGroup, merged map[pgtype.UUID]bool, budget int,
|
||||
@@ -358,9 +356,10 @@ func foldAlbumCopy(
|
||||
return nil
|
||||
}
|
||||
|
||||
// linkCrossRelease links each cross-release group's copies as one song
|
||||
// (#5438): a like on one is a like on all, and the Liked list, shuffle and the
|
||||
// mixes count the song once. A group the pass merged has nothing left to link. Linking an already-linked group changes nothing,
|
||||
// linkCrossRelease links each cross-release group's copies as one song: a
|
||||
// like on one is a like on all, and the Liked list, shuffle and the
|
||||
// mixes count the song once. A group the pass merged has nothing left to link.
|
||||
// Linking an already-linked group changes nothing,
|
||||
// so this runs every pass; likes are shared only when a link is new, since a
|
||||
// like made after it reaches every copy as it is made.
|
||||
func linkCrossRelease(
|
||||
@@ -597,8 +596,8 @@ func (w *DuplicateResolveWorker) tickOnce(ctx context.Context) (waitForScan bool
|
||||
return false
|
||||
}
|
||||
// A scan in flight has listed the files it will reconcile: a copy removed
|
||||
// now is marked present again when it does (7 of the 13 removed at boot
|
||||
// on 2026-10-20, #6169). A run past StuckScanThreshold is a dead one.
|
||||
// now is marked present again when it does. A run past StuckScanThreshold
|
||||
// is a dead one.
|
||||
run, err := q.GetInFlightScanRun(ctx)
|
||||
switch {
|
||||
case err == nil && time.Since(run.StartedAt.Time) <= StuckScanThreshold:
|
||||
|
||||
Reference in New Issue
Block a user