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:
@@ -16,13 +16,14 @@ import (
|
||||
syncpkg "git.fabledsword.com/bvandeusen/minstrel/internal/sync"
|
||||
)
|
||||
|
||||
// Duplicate merge (M400 #3911).
|
||||
// Duplicate merge.
|
||||
|
||||
// ErrDuplicateGroupNotPending means the group was already merged or dismissed,
|
||||
// no longer exists, or no longer has two members to merge.
|
||||
var ErrDuplicateGroupNotPending = errors.New("library: duplicate group is not pending")
|
||||
|
||||
// ErrSurvivorNotInGroup means the copy chosen to keep is not a member of the group.
|
||||
// ErrSurvivorNotInGroup means the copy chosen to keep is not a member of the
|
||||
// group.
|
||||
var ErrSurvivorNotInGroup = errors.New("library: survivor is not a member of the group")
|
||||
|
||||
// MergedCopy is one copy a merge kept or removed.
|
||||
@@ -37,7 +38,7 @@ type MergeResult struct {
|
||||
Survivor MergedCopy
|
||||
Removed []MergedCopy
|
||||
|
||||
// What moved onto the survivor — reported so the operator, and the audit
|
||||
// What moved onto the survivor — reported so an admin, and the audit
|
||||
// log, can see that the history was kept rather than take it on trust.
|
||||
PlayEvents int64
|
||||
SkipEvents int64
|
||||
@@ -60,16 +61,16 @@ type MergeResult struct {
|
||||
// survivor first, and only then deletes the now-empty row.
|
||||
//
|
||||
// It deletes the removed copies' FILES too, and first, before any row changes
|
||||
// (#3918, note #3926). A merge that left the file behind would be undone by the
|
||||
// next scan, which re-imports it as a new track with no history. If a file cannot
|
||||
// be removed, the *FileRemoveError comes back and nothing in the database changes.
|
||||
// With several copies to remove, one file may already be gone when a later one
|
||||
// fails; that copy's row keeps all its history and is marked missing by the next
|
||||
// scan, and retrying the merge picks up where it stopped.
|
||||
// (DeleteTrackFile's order). A merge that left the file behind would be undone
|
||||
// by the next scan, which re-imports it as a new track with no history. If a
|
||||
// file cannot be removed, the *FileRemoveError comes back and nothing in the
|
||||
// database changes. With several copies to remove, one file may already be gone
|
||||
// when a later one fails; that copy's row keeps all its history and is marked
|
||||
// missing by the next scan, and retrying the merge picks up where it stopped.
|
||||
//
|
||||
// Everything else happens in one transaction, which holds a lock on the group so
|
||||
// two merges of it cannot run at once. Sync changes for clients' caches are logged
|
||||
// inside it, the way the playlists service logs its own.
|
||||
// Everything else happens in one transaction, which holds a lock on the group
|
||||
// so two merges of it cannot run at once. Sync changes for clients' caches are
|
||||
// logged inside it, the way the playlists service logs its own.
|
||||
func MergeDuplicateGroup(
|
||||
ctx context.Context, pool *pgxpool.Pool, logger *slog.Logger, dataDir string,
|
||||
groupID, survivorID pgtype.UUID,
|
||||
@@ -152,7 +153,8 @@ func MergeDuplicateGroup(
|
||||
return MergeResult{}, fmt.Errorf("commit merge: %w", err)
|
||||
}
|
||||
|
||||
// After commit, like DeleteTrackFile: a leftover art directory is only disk.
|
||||
// After commit, like DeleteTrackFile: a leftover art directory is only
|
||||
// disk.
|
||||
if dataDir != "" {
|
||||
for _, artistID := range res.DeletedArtistIDs {
|
||||
if err := coverart.CleanupArtistArt(dataDir, artistID); err != nil {
|
||||
@@ -176,11 +178,11 @@ type foldResult struct {
|
||||
}
|
||||
|
||||
// foldTrackInto moves everything the loser row carries onto the survivor, then
|
||||
// deletes the loser row and tidies an album or artist it leaves empty. It is the
|
||||
// row half of a merge, shared by the duplicate merge and the missing-pair pass
|
||||
// (M485): neither touches a file here, and both run it inside their own
|
||||
// transaction. The sync changes it owes clients go into changes, which the
|
||||
// caller logs once before committing.
|
||||
// deletes the loser row and tidies an album or artist it leaves empty. It is
|
||||
// the row half of a merge, shared by the duplicate merge and the missing-pair
|
||||
// pass (PairMissingTracks): neither touches a file here, and both run it inside
|
||||
// their own transaction. The sync changes it owes clients go into changes,
|
||||
// which the caller logs once before committing.
|
||||
func foldTrackInto(
|
||||
ctx context.Context, tq *dbq.Queries, survivorID, loserID pgtype.UUID, changes *mergeChanges,
|
||||
) (foldResult, error) {
|
||||
|
||||
Reference in New Issue
Block a user