Files
minstrel/internal/api/admin_covers.go
T
bvandeusenandClaude Opus 5.5 08a2c06b85 docs: api comments say what the endpoints do, not how they came to be (#6277)
Rewrites the internal/api comment blocks to rule 32: task, milestone and
rule ids gone, the stories behind them restated as the constraint they
left, stale references corrected (the stream secret is wired from config,
the timezone handler already refreshes the scheduler, the Android app is
the native client, the design docs cited are not in the repo). Also
rewraps comment lines over 80 columns left by the earlier batches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:23:58 -04:00

69 lines
2.3 KiB
Go

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 (remote providers pace themselves, 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})
}