Files
silo-server/internal/metadata/pg_errors.go
c5daad0dcb fix(metadata): tolerate missing content item when recording stale IDs (#37)
StaleMediaIDRepository.Upsert inserts (content_id, provider, ...) into
stale_media_ids, which has a foreign key to media_items.content_id. A
metadata refresh can start for an item that is then deleted or merged
away (e.g. by provider-ID canonicalization) before the provider 404
lands and triggers the upsert. The parent row is gone by then, so the
insert fails with a 23503 foreign-key violation
(stale_media_ids_content_id_fkey) and the refresh surfaces a spurious
error — observed in production postgres logs.

When the referenced item no longer exists there is nothing left to track,
so treat that specific FK violation as a logged no-op (at Info, with
provider_id, so a deletion wave stays visible). Other errors still
propagate. The swallow decision is extracted to resolveStaleUpsertError so
it is unit-testable without a database, and the pgconn error-classification
boilerplate is consolidated into a shared isPgConstraintViolation helper
that isProviderIDUniqueConflict now also uses.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 09:30:15 -04:00

23 lines
629 B
Go

package metadata
import (
"errors"
"github.com/jackc/pgx/v5/pgconn"
)
// isPgConstraintViolation reports whether err (or any error it wraps) is a
// Postgres error with the given SQLSTATE code raised by the named constraint.
// Centralizes the errors.As(&pgconn.PgError) + Code/ConstraintName boilerplate
// that several constraint-specific predicates in this package share.
func isPgConstraintViolation(err error, code, constraint string) bool {
if err == nil {
return false
}
var pgErr *pgconn.PgError
if !errors.As(err, &pgErr) {
return false
}
return pgErr.Code == code && pgErr.ConstraintName == constraint
}