🏡 index : quine-global/quintodrome.git

package nativeapi

import (
	"context"
	"errors"
	"net/http"
	"slices"

	"github.com/go-chi/chi/v5"
	"github.com/navidrome/navidrome/core/artwork"
	"github.com/navidrome/navidrome/core/external"
	"github.com/navidrome/navidrome/log"
	"github.com/navidrome/navidrome/model"
)

func (api *Router) addMetadataRoute(r chi.Router) {
	r.Post("/metadata/{kind}/{id}/refresh", api.refreshMetadata())
}

// refreshMetadata clears the artwork state deliberately, so a wrong pick cannot be served from
// cache again; reads fall back to local resolution while the worker re-runs the chain at Bump.
func (api *Router) refreshMetadata() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		kind, _ := model.ParseKind(chi.URLParam(r, "kind"))
		id := chi.URLParam(r, "id")
		if !slices.Contains(artwork.RefreshableKinds, kind) {
			http.Error(w, "invalid artwork kind", http.StatusBadRequest)
			return
		}
		if _, err := artwork.ItemName(ctx, api.ds, kind, id); err != nil {
			if errors.Is(err, model.ErrNotFound) {
				http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
				return
			}
			log.Error(ctx, "Error looking up item to refresh", "kind", kind, "id", id, err)
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}
		if err := artwork.Refresh(ctx, api.ds, kind, id); err != nil {
			log.Error(ctx, "Error refreshing artwork", "kind", kind, "id", id, err)
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}
		if external.HasInfo(kind) {
			// Detached: the request context is cancelled the moment this handler returns 204.
			bg := context.WithoutCancel(ctx)
			go func() {
				if err := api.provider.RefreshInfo(bg, kind, id); err != nil {
					log.Error(bg, "Error refreshing external info", "kind", kind, "id", id, err)
				}
			}()
		}
		w.WriteHeader(http.StatusNoContent)
	}
}