feat: polish & windviz & deploy

This commit is contained in:
Anatoly Antonov 2026-05-30 06:29:39 +09:00
parent 81b8e763bd
commit 465ad00f7b
78 changed files with 20622 additions and 2154 deletions

70
internal/api/handler.go Normal file
View file

@ -0,0 +1,70 @@
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,
},
},
}
}