Merge pull request 'fix(library): drop out-of-range release years instead of failing the album' (#12) from dev into main
This commit was merged in pull request #12.
This commit is contained in:
@@ -208,15 +208,33 @@ func (s *Scanner) resolveAlbum(ctx context.Context, q *dbq.Queries, artistID pgt
|
|||||||
SortTitle: sortKey(title),
|
SortTitle: sortKey(title),
|
||||||
ArtistID: artistID,
|
ArtistID: artistID,
|
||||||
}
|
}
|
||||||
if year > 0 {
|
if d, ok := releaseDateFromYear(year); ok {
|
||||||
params.ReleaseDate = pgtype.Date{
|
params.ReleaseDate = d
|
||||||
Time: time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC),
|
} else if year != 0 {
|
||||||
Valid: true,
|
// year=0 is the no-tag case; anything else getting rejected is a tag
|
||||||
}
|
// we couldn't trust (typo, OOB number, …). Log it so users can chase
|
||||||
|
// down the file but don't fail the album insert over a soft field.
|
||||||
|
s.logger.Warn("library scan: dropping invalid release year",
|
||||||
|
"year", year, "album", title)
|
||||||
}
|
}
|
||||||
return q.UpsertAlbum(ctx, params)
|
return q.UpsertAlbum(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// releaseDateFromYear converts a tag-supplied year into a Postgres date,
|
||||||
|
// returning ok=false if the year is outside what we'll accept. We're
|
||||||
|
// deliberately strict (1..9999): Postgres' date type goes much wider, but
|
||||||
|
// 5-digit years from ID3 tags are always garbage in practice and trigger
|
||||||
|
// SQLSTATE 22008 (datetime field overflow) at insert time.
|
||||||
|
func releaseDateFromYear(year int) (pgtype.Date, bool) {
|
||||||
|
if year < 1 || year > 9999 {
|
||||||
|
return pgtype.Date{}, false
|
||||||
|
}
|
||||||
|
return pgtype.Date{
|
||||||
|
Time: time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
Valid: true,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
|
||||||
// sortKey drops a leading "The " for sortable ordering. Non-English articles
|
// sortKey drops a leading "The " for sortable ordering. Non-English articles
|
||||||
// (Los, Die, Les) can be added if users ask — keeping the rule obvious for now.
|
// (Los, Die, Les) can be added if users ask — keeping the rule obvious for now.
|
||||||
func sortKey(s string) string {
|
func sortKey(s string) string {
|
||||||
|
|||||||
@@ -16,6 +16,31 @@ import (
|
|||||||
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestReleaseDateFromYear(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
in int
|
||||||
|
ok bool
|
||||||
|
label string
|
||||||
|
}{
|
||||||
|
{0, false, "missing tag"},
|
||||||
|
{-1, false, "negative"},
|
||||||
|
{1, true, "lower bound"},
|
||||||
|
{1999, true, "ordinary"},
|
||||||
|
{9999, true, "upper bound"},
|
||||||
|
{10000, false, "five digits"},
|
||||||
|
{99999999, false, "tag corruption"},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
got, ok := releaseDateFromYear(c.in)
|
||||||
|
if ok != c.ok {
|
||||||
|
t.Errorf("%s: ok = %v, want %v", c.label, ok, c.ok)
|
||||||
|
}
|
||||||
|
if ok && (!got.Valid || got.Time.Year() != c.in) {
|
||||||
|
t.Errorf("%s: date = %+v, want year=%d", c.label, got, c.in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestScanner_Integration exercises walk → tag-parse → upsert → incremental
|
// TestScanner_Integration exercises walk → tag-parse → upsert → incremental
|
||||||
// skip against a real Postgres. Gated on MINSTREL_TEST_DATABASE_URL.
|
// skip against a real Postgres. Gated on MINSTREL_TEST_DATABASE_URL.
|
||||||
func TestScanner_Integration(t *testing.T) {
|
func TestScanner_Integration(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user