Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com>
This commit was merged in pull request #110.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/suggest"
|
||||
)
|
||||
|
||||
// postSuggestionBatch starts a manual suggestion batch and answers 202 with
|
||||
// its batch_id and the job_id that GET /jobs/{id} reports on, without
|
||||
// waiting for the job. When a batch is already pending or running it
|
||||
// answers 202 with that batch instead of starting another.
|
||||
func postSuggestionBatch(logger *slog.Logger, svc *suggest.Service) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := svc.StartBatch(r.Context(), suggest.TriggerManual)
|
||||
if err != nil {
|
||||
writeSuggestionError(w, r, logger, "start suggestion batch", err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, r, logger, http.StatusAccepted, b)
|
||||
}
|
||||
}
|
||||
|
||||
// getSuggestionDeck answers GET /suggestions/deck with the pending
|
||||
// suggestions, oldest first, and the batch pending or running, or null.
|
||||
func getSuggestionDeck(logger *slog.Logger, svc *suggest.Service) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
d, err := svc.Deck(r.Context())
|
||||
if err != nil {
|
||||
writeSuggestionError(w, r, logger, "list suggestion deck", err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, r, logger, http.StatusOK, d)
|
||||
}
|
||||
}
|
||||
|
||||
// postSuggestionDecision records Try it (accept) or Pass (decline) on a
|
||||
// suggestion, recording the session's actor as its dinner's updated_by.
|
||||
func postSuggestionDecision(logger *slog.Logger, svc *suggest.Service, accept bool) http.HandlerFunc {
|
||||
decide, action := svc.Decline, "decline suggestion"
|
||||
if accept {
|
||||
decide, action = svc.Accept, "accept suggestion"
|
||||
}
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
actor, ok := actorOrFail(w, r, logger)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
d, err := decide(r.Context(), chi.URLParam(r, "id"), actor.Subject)
|
||||
if err != nil {
|
||||
writeSuggestionError(w, r, logger, action, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, r, logger, http.StatusOK, d)
|
||||
}
|
||||
}
|
||||
|
||||
// writeSuggestionError maps a suggest.Service error to its API error: an
|
||||
// unknown suggestion is 404, and a decision on one already decided the
|
||||
// other way, or whose dinner left the deck, is 409.
|
||||
func writeSuggestionError(w http.ResponseWriter, r *http.Request, logger *slog.Logger, action string, err error) {
|
||||
var decided *suggest.DecidedError
|
||||
switch {
|
||||
case errors.As(err, &decided):
|
||||
writeError(w, r, logger, http.StatusConflict, "suggestion_decided", decided.Error())
|
||||
case errors.Is(err, suggest.ErrDinnerNotSuggested):
|
||||
writeError(w, r, logger, http.StatusConflict, "dinner_not_suggested", err.Error())
|
||||
case errors.Is(err, suggest.ErrNotFound):
|
||||
writeError(w, r, logger, http.StatusNotFound, "not_found", "suggestion not found")
|
||||
default:
|
||||
logger.ErrorContext(r.Context(), action, "error", err)
|
||||
writeError(w, r, logger, http.StatusInternalServerError, "internal", "internal error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user