package database import ( "database/sql" "time" "git.noroutes.net/NoRoutes/vibetunes/internal/idgen" ) // GetCachedExternalMetadata returns a previously fetched MusicBrainz/ // Cover Art Archive response for (entityType, mbid, source), if any. // found is false when nothing has been cached yet — callers decide // whether/how to refresh, this layer never guesses an age-based expiry. func GetCachedExternalMetadata(db *sql.DB, entityType, mbid, source string) (dataJSON string, fetchedAt time.Time, found bool, err error) { var fetchedAtStr string err = db.QueryRow(`SELECT data_json, fetched_at FROM external_metadata_cache WHERE entity_type = ? AND mbid = ? AND source = ?`, entityType, mbid, source).Scan(&dataJSON, &fetchedAtStr) if err == sql.ErrNoRows { return "", time.Time{}, false, nil } if err != nil { return "", time.Time{}, false, err } fetchedAt, _ = time.Parse("2006-01-02T15:04:05.000Z", fetchedAtStr) return dataJSON, fetchedAt, true, nil } // PutCachedExternalMetadata stores (or replaces) the cached response // for (entityType, mbid, source). func PutCachedExternalMetadata(db *sql.DB, entityType, mbid, source, dataJSON string) error { _, err := db.Exec(` INSERT INTO external_metadata_cache (id, entity_type, mbid, source, data_json, fetched_at) VALUES (?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ','now')) ON CONFLICT(entity_type, mbid, source) DO UPDATE SET data_json = excluded.data_json, fetched_at = excluded.fetched_at`, idgen.New("emc"), entityType, mbid, source, dataJSON) return err }