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:
@@ -96,7 +96,7 @@ func (q *Queries) EndGrab(ctx context.Context, arg EndGrabParams) error {
|
||||
|
||||
const getAcquisitionSettings = `-- name: GetAcquisitionSettings :one
|
||||
|
||||
SELECT id, auto_grab, search_interval_hours, allowed_qualities, last_pass_at, last_pass, updated_at, import_root, seed_ratio, seed_days, stall_hours, library_listing_started_at, library_listed_at, library_unlisted FROM acquisition_settings WHERE id = true
|
||||
SELECT id, auto_grab, search_interval_hours, allowed_qualities, last_pass_at, last_pass, updated_at, import_root, seed_ratio, seed_days, stall_hours, library_listing_started_at, library_listed_at, library_unlisted, upgrade_until FROM acquisition_settings WHERE id = true
|
||||
`
|
||||
|
||||
// Searching for wants and grabbing releases (M502 #5521).
|
||||
@@ -118,6 +118,7 @@ func (q *Queries) GetAcquisitionSettings(ctx context.Context) (AcquisitionSettin
|
||||
&i.LibraryListingStartedAt,
|
||||
&i.LibraryListedAt,
|
||||
&i.LibraryUnlisted,
|
||||
&i.UpgradeUntil,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -201,6 +202,7 @@ func (q *Queries) GetWantCandidate(ctx context.Context, arg GetWantCandidatePara
|
||||
|
||||
const getWantForSearch = `-- name: GetWantForSearch :one
|
||||
SELECT w.id, w.release_group_mbid, w.artist_mbid, w.artist_name, w.title, w.reason, w.fulfilled_at,
|
||||
w.upgrade, w.held_tier, w.held_quality, w.album_id,
|
||||
COALESCE(NULLIF(w.primary_type, ''), g.primary_type, '')::text AS primary_type,
|
||||
COALESCE(g.secondary_types, '{}')::text[] AS secondary_types,
|
||||
COALESCE(NULLIF(w.first_release_date, ''), g.first_release_date, '')::text AS first_release_date
|
||||
@@ -217,6 +219,10 @@ type GetWantForSearchRow struct {
|
||||
Title string
|
||||
Reason string
|
||||
FulfilledAt pgtype.Timestamptz
|
||||
Upgrade string
|
||||
HeldTier string
|
||||
HeldQuality string
|
||||
AlbumID pgtype.UUID
|
||||
PrimaryType string
|
||||
SecondaryTypes []string
|
||||
FirstReleaseDate string
|
||||
@@ -233,6 +239,10 @@ func (q *Queries) GetWantForSearch(ctx context.Context, id pgtype.UUID) (GetWant
|
||||
&i.Title,
|
||||
&i.Reason,
|
||||
&i.FulfilledAt,
|
||||
&i.Upgrade,
|
||||
&i.HeldTier,
|
||||
&i.HeldQuality,
|
||||
&i.AlbumID,
|
||||
&i.PrimaryType,
|
||||
&i.SecondaryTypes,
|
||||
&i.FirstReleaseDate,
|
||||
@@ -449,16 +459,20 @@ func (q *Queries) ListWantCandidates(ctx context.Context, wantID pgtype.UUID) ([
|
||||
}
|
||||
|
||||
const listWantsDueForSearch = `-- name: ListWantsDueForSearch :many
|
||||
SELECT w.id, w.release_group_mbid, w.artist_name, w.title, w.reason,
|
||||
SELECT w.id, w.release_group_mbid, w.artist_name, w.title, w.reason, w.upgrade, w.held_tier, w.held_quality,
|
||||
COALESCE(NULLIF(w.primary_type, ''), g.primary_type, '')::text AS primary_type,
|
||||
COALESCE(g.secondary_types, '{}')::text[] AS secondary_types,
|
||||
COALESCE(NULLIF(w.first_release_date, ''), g.first_release_date, '')::text AS first_release_date
|
||||
FROM wants w
|
||||
LEFT JOIN mb_release_groups g ON g.mbid = w.release_group_mbid
|
||||
WHERE w.fulfilled_at IS NULL
|
||||
WHERE (w.fulfilled_at IS NULL OR w.upgrade <> '')
|
||||
AND NOT EXISTS (SELECT 1 FROM grabs gr WHERE gr.want_id = w.id AND gr.ended_at IS NULL)
|
||||
AND (w.searched_at IS NULL OR w.searched_at < now() - make_interval(hours => $1::int))
|
||||
ORDER BY w.searched_at IS NOT NULL,
|
||||
AND (w.searched_at IS NULL
|
||||
OR w.searched_at < now() - make_interval(hours => CASE WHEN w.fulfilled_at IS NULL
|
||||
THEN $1::int
|
||||
ELSE GREATEST($1::int, 168) END))
|
||||
ORDER BY w.fulfilled_at IS NOT NULL,
|
||||
w.searched_at IS NOT NULL,
|
||||
CASE w.reason WHEN 'request' THEN 0 WHEN 'missing' THEN 1 ELSE 2 END,
|
||||
w.searched_at NULLS FIRST, w.wanted_at, w.id
|
||||
LIMIT $2
|
||||
@@ -475,14 +489,18 @@ type ListWantsDueForSearchRow struct {
|
||||
ArtistName string
|
||||
Title string
|
||||
Reason string
|
||||
Upgrade string
|
||||
HeldTier string
|
||||
HeldQuality string
|
||||
PrimaryType string
|
||||
SecondaryTypes []string
|
||||
FirstReleaseDate string
|
||||
}
|
||||
|
||||
// Open wants with no download running that were never searched or not since
|
||||
// @hours ago: never-searched first, then requests, then missing files, then
|
||||
// followed artists' releases.
|
||||
// Wants with no download running that were never searched or not since
|
||||
// @hours ago: open wants first (never-searched, then requests, then missing
|
||||
// files, then followed artists' releases), then held albums wanted for an
|
||||
// upgrade (#5524), which are searched at most weekly.
|
||||
func (q *Queries) ListWantsDueForSearch(ctx context.Context, arg ListWantsDueForSearchParams) ([]ListWantsDueForSearchRow, error) {
|
||||
rows, err := q.db.Query(ctx, listWantsDueForSearch, arg.Hours, arg.MaxRows)
|
||||
if err != nil {
|
||||
@@ -498,6 +516,9 @@ func (q *Queries) ListWantsDueForSearch(ctx context.Context, arg ListWantsDueFor
|
||||
&i.ArtistName,
|
||||
&i.Title,
|
||||
&i.Reason,
|
||||
&i.Upgrade,
|
||||
&i.HeldTier,
|
||||
&i.HeldQuality,
|
||||
&i.PrimaryType,
|
||||
&i.SecondaryTypes,
|
||||
&i.FirstReleaseDate,
|
||||
@@ -609,9 +630,10 @@ UPDATE acquisition_settings
|
||||
seed_ratio = $5,
|
||||
seed_days = $6,
|
||||
stall_hours = $7,
|
||||
upgrade_until = $8,
|
||||
updated_at = now()
|
||||
WHERE id = true
|
||||
RETURNING id, auto_grab, search_interval_hours, allowed_qualities, last_pass_at, last_pass, updated_at, import_root, seed_ratio, seed_days, stall_hours, library_listing_started_at, library_listed_at, library_unlisted
|
||||
RETURNING id, auto_grab, search_interval_hours, allowed_qualities, last_pass_at, last_pass, updated_at, import_root, seed_ratio, seed_days, stall_hours, library_listing_started_at, library_listed_at, library_unlisted, upgrade_until
|
||||
`
|
||||
|
||||
type UpdateAcquisitionSettingsParams struct {
|
||||
@@ -622,6 +644,7 @@ type UpdateAcquisitionSettingsParams struct {
|
||||
SeedRatio float32
|
||||
SeedDays int32
|
||||
StallHours int32
|
||||
UpgradeUntil string
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAcquisitionSettings(ctx context.Context, arg UpdateAcquisitionSettingsParams) (AcquisitionSetting, error) {
|
||||
@@ -633,6 +656,7 @@ func (q *Queries) UpdateAcquisitionSettings(ctx context.Context, arg UpdateAcqui
|
||||
arg.SeedRatio,
|
||||
arg.SeedDays,
|
||||
arg.StallHours,
|
||||
arg.UpgradeUntil,
|
||||
)
|
||||
var i AcquisitionSetting
|
||||
err := row.Scan(
|
||||
@@ -650,6 +674,7 @@ func (q *Queries) UpdateAcquisitionSettings(ctx context.Context, arg UpdateAcqui
|
||||
&i.LibraryListingStartedAt,
|
||||
&i.LibraryListedAt,
|
||||
&i.LibraryUnlisted,
|
||||
&i.UpgradeUntil,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user