package api import ( "context" "errors" "net/http" "github.com/go-chi/chi/v5" "github.com/jackc/pgx/v5" "git.fabledsword.com/bvandeusen/minstrel/internal/apierror" "git.fabledsword.com/bvandeusen/minstrel/internal/coverart" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" ) type adminCoverRefetchResp struct { AlbumID string `json:"album_id"` CoverArtPath *string `json:"cover_art_path"` CoverArtSource *string `json:"cover_art_source"` } // handleAdminAlbumRefetchCover implements POST /api/admin/albums/{id}/cover/refetch. // Synchronously clears + re-runs the enricher for one album. func (h *handlers) handleAdminAlbumRefetchCover(w http.ResponseWriter, r *http.Request) { albumID, ok := parseUUID(chi.URLParam(r, "id")) if !ok { writeErr(w, apierror.BadRequest("bad_request", "invalid album id")) return } if err := h.coverart.RetryAlbum(r.Context(), albumID); err != nil { if errors.Is(err, coverart.ErrNotFound) || errors.Is(err, pgx.ErrNoRows) { writeErr(w, &apierror.Error{Status: http.StatusNotFound, Code: "not_found", Message: "album not found"}) return } writeErrWithLog(w, h.logger, "admin: cover refetch failed", apierror.InternalMsg("refetch failed", err)) return } row, err := dbq.New(h.pool).GetAlbumWithFirstTrackPath(r.Context(), albumID) if err != nil { writeErrWithLog(w, h.logger, "admin: post-refetch read failed", apierror.InternalMsg("read failed", err)) return } writeJSON(w, http.StatusOK, adminCoverRefetchResp{ AlbumID: uuidToString(albumID), CoverArtPath: row.CoverArtPath, CoverArtSource: row.CoverArtSource, }) } type adminBulkRefetchResp struct { Started bool `json:"started"` } // handleAdminBulkRefetchCovers implements POST /api/admin/covers/refetch-missing. // Returns immediately; the drain runs UNBOUNDED in a background goroutine // (#388 — no global cap; remote providers self-throttle per provider, local // sources run at disk speed). The count is unknowable synchronously, so the // response just acknowledges the drain started. func (h *handlers) handleAdminBulkRefetchCovers(w http.ResponseWriter, _ *http.Request) { go func() { bgCtx := context.Background() if _, err := h.coverart.EnrichRetryMissing(bgCtx, -1); err != nil { h.logger.Warn("admin: bulk cover refetch failed", "err", err) } }() writeJSON(w, http.StatusOK, adminBulkRefetchResp{Started: true}) }