70 lines
2.1 KiB
Go
70 lines
2.1 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"predictor-refactored/internal/api/async"
|
|
"predictor-refactored/internal/datasets"
|
|
"predictor-refactored/internal/elevation"
|
|
"predictor-refactored/internal/engine"
|
|
"predictor-refactored/internal/metrics"
|
|
"predictor-refactored/internal/windviz"
|
|
apirest "predictor-refactored/pkg/rest"
|
|
)
|
|
|
|
// Handler implements the ogen-generated apirest.Handler interface for every
|
|
// operation in the OpenAPI spec. Operation methods are grouped by concern
|
|
// across prediction.go, datasets.go, and wind.go.
|
|
type Handler struct {
|
|
mgr *datasets.Manager
|
|
elev *elevation.Dataset
|
|
async *async.Manager
|
|
metrics metrics.Sink
|
|
cache *windviz.Cache
|
|
started time.Time
|
|
log *zap.Logger
|
|
}
|
|
|
|
var _ apirest.Handler = (*Handler)(nil)
|
|
|
|
// terrain returns the elevation dataset as an engine.TerrainProvider, or an
|
|
// untyped nil interface when no elevation dataset is loaded. Returning the
|
|
// concrete nil *elevation.Dataset directly would produce a non-nil interface
|
|
// wrapping a nil pointer, which then panics on first use — so the nil check
|
|
// must happen here, on the concrete type.
|
|
func (h *Handler) terrain() engine.TerrainProvider {
|
|
if h.elev == nil {
|
|
return nil
|
|
}
|
|
return h.elev
|
|
}
|
|
|
|
// NewError converts an error returned by a handler into the spec's default
|
|
// error response. Handlers return *apirest.DefaultErrorStatusCode (via the
|
|
// apiError helper) to control the status code; anything else is a 500.
|
|
func (h *Handler) NewError(_ context.Context, err error) *apirest.DefaultErrorStatusCode {
|
|
var coded *apirest.DefaultErrorStatusCode
|
|
if errors.As(err, &coded) {
|
|
return coded
|
|
}
|
|
h.log.Error("unhandled handler error", zap.Error(err))
|
|
return apiError(http.StatusInternalServerError, err.Error())
|
|
}
|
|
|
|
// apiError builds a coded error response carrying an HTTP status.
|
|
func apiError(status int, description string) *apirest.DefaultErrorStatusCode {
|
|
return &apirest.DefaultErrorStatusCode{
|
|
StatusCode: status,
|
|
Response: apirest.Error{
|
|
Error: apirest.ErrorError{
|
|
Type: http.StatusText(status),
|
|
Description: description,
|
|
},
|
|
},
|
|
}
|
|
}
|