feat: a held album below the quality you settle for, or holding a video rip, stays wanted for a better copy, and the import replaces the old tracks with their likes and plays carried over (M502 #5524)
release / govulncheck (push) Successful in 15s
release / web (push) Successful in 1m23s
release / go (push) Successful in 1m41s
release / integration (push) Successful in 5m20s
release / android (push) Successful in 5m28s
release / Build signed APK (releases and dev) (push) Successful in 5m30s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 27s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 15s
release / web (push) Successful in 1m23s
release / go (push) Successful in 1m41s
release / integration (push) Successful in 5m20s
release / android (push) Successful in 5m28s
release / Build signed APK (releases and dev) (push) Successful in 5m30s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 27s
release / Verify release artifacts (tag releases only) (push) Skipped
- acquisition_settings.upgrade_until (default High quality lossy, Lidarr's cutoff, note #5527; "" is off), an "Upgrade until" row under Searching. - The wanted worker judges held albums hourly: tier per format from size per second (the scanner records no bitrate), the album's worst. Below the cutoff it is wanted for quality; a video rip among its tracks always. - The schedule searches upgrades weekly, after open wants; a release no better than the copy held is refused ("not_better"). - The import matches each file to the track it would replace (recording, then disc/track) and replaces it when it is a rip or the file is a better tier: over the same path in one rename, or filed beside it and the old track folded in (library.ReplaceTrack: file first, then foldTrackInto). Nothing better: the release is set aside. - Collection › Upgrades (Lidarr's Cutoff Unmet); Suspect sources says when a clean copy was looked for instead of Lidarr's search. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+31
-13
@@ -48,7 +48,8 @@ const (
|
||||
passTimeout = 15 * time.Minute
|
||||
)
|
||||
|
||||
// ErrWantHeld: the want is already answered by the library.
|
||||
// ErrWantHeld: the want is already answered by the library, and is not
|
||||
// wanted for a better copy.
|
||||
var ErrWantHeld = errors.New("wanted: the library already holds this album")
|
||||
|
||||
// Searcher searches for wants and grabs what they need.
|
||||
@@ -167,8 +168,9 @@ func (s *Searcher) pass(ctx context.Context) Report {
|
||||
rep.Paced = ctx.Err() == nil
|
||||
return rep
|
||||
}
|
||||
want := s.wantFor(ctx, row.ID, row.ArtistName, row.Title, row.PrimaryType, row.SecondaryTypes,
|
||||
row.FirstReleaseDate, row.ReleaseGroupMbid)
|
||||
want := s.wantFor(ctx, searchRow{id: row.ID, artist: row.ArtistName, title: row.Title,
|
||||
primary: row.PrimaryType, secondary: row.SecondaryTypes, date: row.FirstReleaseDate,
|
||||
group: row.ReleaseGroupMbid, upgrade: row.Upgrade, heldTier: row.HeldTier, held: row.HeldQuality})
|
||||
out := s.one(ctx, svc, want, settings.AutoGrab)
|
||||
rep.Looked++
|
||||
switch out.Outcome {
|
||||
@@ -186,17 +188,31 @@ func (s *Searcher) pass(ctx context.Context) Report {
|
||||
return rep
|
||||
}
|
||||
|
||||
// searchRow is what a search needs of a wants row.
|
||||
type searchRow struct {
|
||||
id pgtype.UUID
|
||||
artist, title, primary, date, group string
|
||||
secondary []string
|
||||
// upgrade, heldTier and held: a held album wanted for a better copy
|
||||
// (#5524), and the copy it has.
|
||||
upgrade, heldTier, held string
|
||||
}
|
||||
|
||||
// wantFor describes a want for the matcher, with its editions' track counts
|
||||
// from the catalogue (read from MusicBrainz the first time when it can be).
|
||||
func (s *Searcher) wantFor(ctx context.Context, id pgtype.UUID, artist, title, primary string, secondary []string, date, group string) acquire.Want {
|
||||
w := acquire.Want{ID: id, Want: release.Want{
|
||||
Artist: artist, Title: title, Year: yearOf(date), PrimaryType: primary, SecondaryTypes: secondary,
|
||||
// A held album wanted for better quality takes its copy's tier as a floor.
|
||||
func (s *Searcher) wantFor(ctx context.Context, r searchRow) acquire.Want {
|
||||
w := acquire.Want{ID: r.id, Want: release.Want{
|
||||
Artist: r.artist, Title: r.title, Year: yearOf(r.date), PrimaryType: r.primary, SecondaryTypes: r.secondary,
|
||||
}}
|
||||
if r.upgrade == UpgradeQuality && release.KnownTier(r.heldTier) {
|
||||
w.Floor, w.Held = release.Tier(r.heldTier), r.held
|
||||
}
|
||||
q := dbq.New(s.pool)
|
||||
span, err := q.EditionTrackSpan(ctx, group)
|
||||
span, err := q.EditionTrackSpan(ctx, r.group)
|
||||
if err == nil && span.MinTracks == 0 && s.cat != nil {
|
||||
if _, rerr := s.cat.Releases(ctx, group); rerr == nil {
|
||||
span, err = q.EditionTrackSpan(ctx, group)
|
||||
if _, rerr := s.cat.Releases(ctx, r.group); rerr == nil {
|
||||
span, err = q.EditionTrackSpan(ctx, r.group)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
@@ -329,15 +345,17 @@ func (s *Searcher) Take(ctx context.Context, id pgtype.UUID, key string, force b
|
||||
return took, nil
|
||||
}
|
||||
|
||||
// load reads an open want for a search.
|
||||
// load reads a want for a search: an open one, or a held album wanted for a
|
||||
// better copy (#5524).
|
||||
func (s *Searcher) load(ctx context.Context, id pgtype.UUID) (acquire.Want, error) {
|
||||
row, err := dbq.New(s.pool).GetWantForSearch(ctx, id)
|
||||
if err != nil {
|
||||
return acquire.Want{}, err
|
||||
}
|
||||
if row.FulfilledAt.Valid {
|
||||
if row.FulfilledAt.Valid && row.Upgrade == "" {
|
||||
return acquire.Want{}, ErrWantHeld
|
||||
}
|
||||
return s.wantFor(ctx, row.ID, row.ArtistName, row.Title, row.PrimaryType, row.SecondaryTypes,
|
||||
row.FirstReleaseDate, row.ReleaseGroupMbid), nil
|
||||
return s.wantFor(ctx, searchRow{id: row.ID, artist: row.ArtistName, title: row.Title,
|
||||
primary: row.PrimaryType, secondary: row.SecondaryTypes, date: row.FirstReleaseDate,
|
||||
group: row.ReleaseGroupMbid, upgrade: row.Upgrade, heldTier: row.HeldTier, held: row.HeldQuality}), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user