63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package async
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"predictor-refactored/internal/api/httpjson"
|
|
"predictor-refactored/internal/api/v2"
|
|
)
|
|
|
|
// Handler implements the /api/v1/predictions{,/{id}} endpoints.
|
|
type Handler struct {
|
|
mgr *Manager
|
|
}
|
|
|
|
// NewHandler wires a handler.
|
|
func NewHandler(mgr *Manager) *Handler { return &Handler{mgr: mgr} }
|
|
|
|
// Register installs the async routes on mux.
|
|
func (h *Handler) Register(mux *http.ServeMux) {
|
|
mux.HandleFunc("POST /api/v1/predictions", h.create)
|
|
mux.HandleFunc("GET /api/v1/predictions/{id}", h.get)
|
|
mux.HandleFunc("DELETE /api/v1/predictions/{id}", h.cancel)
|
|
}
|
|
|
|
func (h *Handler) create(w http.ResponseWriter, r *http.Request) {
|
|
var req v2.PredictionRequest
|
|
dec := json.NewDecoder(r.Body)
|
|
dec.DisallowUnknownFields()
|
|
if err := dec.Decode(&req); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid body: "+err.Error())
|
|
return
|
|
}
|
|
info, accepted := h.mgr.Enqueue(req)
|
|
if !accepted {
|
|
writeJSON(w, http.StatusServiceUnavailable, info)
|
|
return
|
|
}
|
|
w.Header().Set("Location", "/api/v1/predictions/"+info.ID)
|
|
writeJSON(w, http.StatusAccepted, info)
|
|
}
|
|
|
|
func (h *Handler) get(w http.ResponseWriter, r *http.Request) {
|
|
id := r.PathValue("id")
|
|
info, ok := h.mgr.Get(id)
|
|
if !ok {
|
|
writeError(w, http.StatusNotFound, "prediction job not found")
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, info)
|
|
}
|
|
|
|
func (h *Handler) cancel(w http.ResponseWriter, r *http.Request) {
|
|
id := r.PathValue("id")
|
|
if !h.mgr.Cancel(id) {
|
|
writeError(w, http.StatusConflict, "job not found or already terminal")
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
var writeJSON = httpjson.Write
|
|
var writeError = httpjson.Error
|