fix(lidarrquarantine): translate FK violation to ErrTrackNotFound + drop unneeded *string AlbumTitle
- Flag now detects Postgres SQLSTATE 23503 (foreign_key_violation) on
UpsertQuarantine and surfaces ErrTrackNotFound instead of a wrapped
generic. T8's handler can now return 404 track_not_found cleanly.
Constraint-name guard ('track' substring) keeps a future user_id FK from
mis-mapping to the same error.
- AdminQueueRow.AlbumTitle is now string (not *string). albums.title is
NOT NULL upstream; the empty-string-to-nil dance was answering a
nullability question that doesn't exist in the schema.
- Add TestFlag_NonexistentTrackReturnsErrTrackNotFound covering the new
branch.
This commit is contained in:
@@ -9,8 +9,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
@@ -64,10 +66,15 @@ func (s *Service) Flag(ctx context.Context, userID, trackID pgtype.UUID, reason
|
||||
Notes: notesPtr,
|
||||
})
|
||||
if err != nil {
|
||||
// FK violation on track_id surfaces here as a postgres error;
|
||||
// callers can treat any error as "track doesn't exist or DB issue."
|
||||
// Distinguishing FK violation specifically isn't worth the extra
|
||||
// dependency on pgconn just for one branch.
|
||||
// FK violation on track_id (no such track) → ErrTrackNotFound so the
|
||||
// handler can return 404 instead of a generic 500. Code 23503 is the
|
||||
// Postgres SQLSTATE for foreign_key_violation; the constraint check
|
||||
// guards against future FKs (e.g. user_id) firing the same code.
|
||||
var pgErr *pgconn.PgError
|
||||
if errors.As(err, &pgErr) && pgErr.Code == "23503" &&
|
||||
(pgErr.ConstraintName == "" || strings.Contains(pgErr.ConstraintName, "track")) {
|
||||
return dbq.LidarrQuarantine{}, ErrTrackNotFound
|
||||
}
|
||||
return dbq.LidarrQuarantine{}, fmt.Errorf("upsert: %w", err)
|
||||
}
|
||||
return row, nil
|
||||
@@ -102,7 +109,7 @@ type AdminQueueRow struct {
|
||||
TrackID pgtype.UUID
|
||||
TrackTitle string
|
||||
ArtistName string
|
||||
AlbumTitle *string
|
||||
AlbumTitle string
|
||||
AlbumID pgtype.UUID
|
||||
LidarrAlbumMBID *string
|
||||
ReportCount int32
|
||||
@@ -149,16 +156,11 @@ func (s *Service) ListAdminQueue(ctx context.Context) ([]AdminQueueRow, error) {
|
||||
CreatedAt: rep.CreatedAt,
|
||||
})
|
||||
}
|
||||
var albumTitle *string
|
||||
if r.AlbumTitle != "" {
|
||||
t := r.AlbumTitle
|
||||
albumTitle = &t
|
||||
}
|
||||
out = append(out, AdminQueueRow{
|
||||
TrackID: r.TrackID,
|
||||
TrackTitle: r.TrackTitle,
|
||||
ArtistName: r.ArtistName,
|
||||
AlbumTitle: albumTitle,
|
||||
AlbumTitle: r.AlbumTitle,
|
||||
AlbumID: r.AlbumID,
|
||||
LidarrAlbumMBID: r.LidarrAlbumMbid,
|
||||
ReportCount: r.ReportCount,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/db"
|
||||
@@ -117,6 +118,21 @@ func TestFlag_UpsertOnSecondFlag(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlag_NonexistentTrackReturnsErrTrackNotFound(t *testing.T) {
|
||||
pool := newPool(t)
|
||||
user := seedUser(t, pool, "alice")
|
||||
|
||||
var bogus pgtype.UUID
|
||||
bogus.Bytes = [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
||||
bogus.Valid = true
|
||||
|
||||
svc := NewService(pool, lidarrconfig.New(pool), nil)
|
||||
_, err := svc.Flag(context.Background(), user.ID, bogus, "bad_rip", "")
|
||||
if !errors.Is(err, ErrTrackNotFound) {
|
||||
t.Errorf("err = %v, want ErrTrackNotFound", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlag_BadReasonRejected(t *testing.T) {
|
||||
pool := newPool(t)
|
||||
user := seedUser(t, pool, "alice")
|
||||
|
||||
Reference in New Issue
Block a user