Compare commits
4 commits
419c07886c
...
b9c1a98895
| Author | SHA1 | Date | |
|---|---|---|---|
| b9c1a98895 | |||
| 5240968c33 | |||
| bcb9ace54c | |||
| 5158c5d7c9 |
43 changed files with 5100 additions and 45 deletions
|
|
@ -14,7 +14,7 @@ paths:
|
||||||
name: parameters
|
name: parameters
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Prediction/Parameters'
|
$ref: '#/components/schemas/PredictionParameters'
|
||||||
style: form
|
style: form
|
||||||
explode: true
|
explode: true
|
||||||
requestBody:
|
requestBody:
|
||||||
|
|
@ -22,12 +22,33 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Prediction/Parameters'
|
$ref: '#/components/schemas/PredictionParameters'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: "Prediction response"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/PredictionResult'
|
||||||
|
default:
|
||||||
|
description: Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Prediction:
|
Error:
|
||||||
Parameters:
|
type: object
|
||||||
|
required:
|
||||||
|
- message
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
details:
|
||||||
|
type: string
|
||||||
|
PredictionParameters:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
launch_latitude: # TODO: altitude not required with fallback to https://github.com/priyeshpatel/ruaumoko Go analog
|
launch_latitude: # TODO: altitude not required with fallback to https://github.com/priyeshpatel/ruaumoko Go analog
|
||||||
|
|
@ -69,3 +90,39 @@ components:
|
||||||
dataset:
|
dataset:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
PredictionResult:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- metadata
|
||||||
|
- prediction
|
||||||
|
properties:
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- complete_datetime
|
||||||
|
- start_datetime
|
||||||
|
properties:
|
||||||
|
complete_datetime:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
start_datetime:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
prediction:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- stage
|
||||||
|
- trajectory
|
||||||
|
properties:
|
||||||
|
stage:
|
||||||
|
type: string
|
||||||
|
enum: ["ascent", "descent"]
|
||||||
|
trajectory:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- datetime
|
||||||
|
- latitude
|
||||||
41
cmd/api/main.go
Normal file
41
cmd/api/main.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/service"
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/transport/rest"
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/transport/rest/handler"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
servicePrefix = "PREDICTOR"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
lg, err := zap.NewProduction()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := service.New()
|
||||||
|
|
||||||
|
handler := handler.New(svc)
|
||||||
|
|
||||||
|
restConfig, err := rest.NewConfig(servicePrefix)
|
||||||
|
if err != nil {
|
||||||
|
lg.Fatal("failed to init transport config", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
transport, err := rest.New(lg, handler, restConfig)
|
||||||
|
if err != nil {
|
||||||
|
lg.Fatal("failed to init transport", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
transport.Run()
|
||||||
|
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
lg.Error("panic occured", zap.Any("recover", r))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
go.mod
34
go.mod
|
|
@ -1,3 +1,37 @@
|
||||||
module git.intra.yksa.space/gsn/predictor
|
module git.intra.yksa.space/gsn/predictor
|
||||||
|
|
||||||
go 1.24.4
|
go 1.24.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/caarlos0/env/v11 v11.3.1
|
||||||
|
github.com/go-faster/errors v0.7.1
|
||||||
|
github.com/go-faster/jx v1.1.0
|
||||||
|
github.com/ogen-go/ogen v1.14.0
|
||||||
|
go.opentelemetry.io/otel v1.36.0
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0
|
||||||
|
go.uber.org/zap v1.27.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||||
|
github.com/edsrzf/mmap-go v1.2.0 // indirect
|
||||||
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
|
github.com/go-faster/yaml v0.4.6 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/nilsmagnus/grib v1.2.8 // indirect
|
||||||
|
github.com/segmentio/asm v1.2.0 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
|
||||||
|
golang.org/x/net v0.40.0 // indirect
|
||||||
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
|
golang.org/x/text v0.25.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
)
|
||||||
|
|
|
||||||
81
go.sum
Normal file
81
go.sum
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA=
|
||||||
|
github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||||
|
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
|
github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84=
|
||||||
|
github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
|
||||||
|
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
|
||||||
|
github.com/go-faster/jx v1.1.0 h1:ZsW3wD+snOdmTDy9eIVgQdjUpXRRV4rqW8NS3t+20bg=
|
||||||
|
github.com/go-faster/jx v1.1.0/go.mod h1:vKDNikrKoyUmpzaJ0OkIkRQClNHFX/nF3dnTJZb3skg=
|
||||||
|
github.com/go-faster/yaml v0.4.6 h1:lOK/EhI04gCpPgPhgt0bChS6bvw7G3WwI8xxVe0sw9I=
|
||||||
|
github.com/go-faster/yaml v0.4.6/go.mod h1:390dRIvV4zbnO7qC9FGo6YYutc+wyyUSHBgbXL52eXk=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/nilsmagnus/grib v1.2.8 h1:H7ch/1/agaCqM3MC8hW1Ft+EJ+q2XB757uml/IfPvp4=
|
||||||
|
github.com/nilsmagnus/grib v1.2.8/go.mod h1:XHm+5zuoOk0NSIWaGmA3JaAxI4i50YvD1L1vz+aqPOQ=
|
||||||
|
github.com/ogen-go/ogen v1.14.0 h1:TU1Nj4z9UBsAfTkf+IhuNNp7igdFQKqkk9+6/y4XuWg=
|
||||||
|
github.com/ogen-go/ogen v1.14.0/go.mod h1:Iw1vkqkx6SU7I9th5ceP+fVPJ6Wge4e3kAVzAxJEpPE=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
|
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||||
|
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
||||||
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
7
internal/pkg/ds/predictor.go
Normal file
7
internal/pkg/ds/predictor.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package ds
|
||||||
|
|
||||||
|
type PredictionParameters struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredicitonResult struct {
|
||||||
|
}
|
||||||
29
internal/pkg/errcodes/errcodes.go
Normal file
29
internal/pkg/errcodes/errcodes.go
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package errcodes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ErrorCode struct {
|
||||||
|
StatusCode int
|
||||||
|
Message string
|
||||||
|
Details string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(statusCode int, message string, details ...string) *ErrorCode {
|
||||||
|
return &ErrorCode{
|
||||||
|
StatusCode: statusCode,
|
||||||
|
Message: message,
|
||||||
|
Details: strings.Join(details, " "),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ErrorCode) Error() string {
|
||||||
|
return e.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNoDataset = New(http.StatusNotFound, "no grib dataset found")
|
||||||
|
ErrOutOfBounds = New(http.StatusBadRequest, "requested time is out of bounds")
|
||||||
|
)
|
||||||
40
internal/pkg/grib/cache.go
Normal file
40
internal/pkg/grib/cache.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type vec [2]float64
|
||||||
|
|
||||||
|
type item struct {
|
||||||
|
v vec
|
||||||
|
exp time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type memCache struct {
|
||||||
|
ttl time.Duration
|
||||||
|
m sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *memCache) get(k uint64) (vec, bool) {
|
||||||
|
if v, ok := c.m.Load(k); ok {
|
||||||
|
it := v.(item)
|
||||||
|
if time.Now().Before(it.exp) {
|
||||||
|
return it.v, true
|
||||||
|
}
|
||||||
|
c.m.Delete(k)
|
||||||
|
}
|
||||||
|
return vec{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *memCache) set(k uint64, v vec) { c.m.Store(k, item{v, time.Now().Add(c.ttl)}) }
|
||||||
|
|
||||||
|
func encodeVec(v vec) []byte {
|
||||||
|
var b [16]byte
|
||||||
|
binary.LittleEndian.PutUint64(b[:8], math.Float64bits(v[0]))
|
||||||
|
binary.LittleEndian.PutUint64(b[8:], math.Float64bits(v[1]))
|
||||||
|
return b[:]
|
||||||
|
}
|
||||||
24
internal/pkg/grib/config.go
Normal file
24
internal/pkg/grib/config.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
env "github.com/caarlos0/env/v11"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
DatasetURL url.URL `env:"DATASET_URL"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig(servicePrefix string) (*Config, error) {
|
||||||
|
cfg := &Config{}
|
||||||
|
|
||||||
|
if err := env.ParseWithOptions(cfg, env.Options{
|
||||||
|
PrefixTagName: fmt.Sprintf("%s_GRIB_", servicePrefix),
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
43
internal/pkg/grib/cube.go
Normal file
43
internal/pkg/grib/cube.go
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
mmap "github.com/edsrzf/mmap-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cube struct {
|
||||||
|
mm mmap.MMap // read‑only, U followed by V (float32 LE)
|
||||||
|
t, p, lat, lon int
|
||||||
|
bytesPerVar int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func openCube(path string) (*cube, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mm, err := mmap.Map(f, mmap.RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nT = 17
|
||||||
|
nP = 34
|
||||||
|
nLat = 361
|
||||||
|
nLon = 720
|
||||||
|
)
|
||||||
|
|
||||||
|
return &cube{mm: mm, t: nT, p: nP, lat: nLat, lon: nLon, bytesPerVar: int64(nT * nP * nLat * nLon * 4)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cube) val(varIdx, ti, pi, y, x int) float32 {
|
||||||
|
idx := (((ti*c.p+pi)*c.lat + y) * c.lon) + x
|
||||||
|
off := int64(varIdx)*c.bytesPerVar + int64(idx)*4
|
||||||
|
bits := binary.LittleEndian.Uint32(c.mm[off : off+4])
|
||||||
|
return math.Float32frombits(bits)
|
||||||
|
}
|
||||||
6
internal/pkg/grib/dataset.go
Normal file
6
internal/pkg/grib/dataset.go
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
type dataset struct {
|
||||||
|
cube *cube
|
||||||
|
runUTC int64 // unix seconds
|
||||||
|
}
|
||||||
69
internal/pkg/grib/downloader.go
Normal file
69
internal/pkg/grib/downloader.go
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NOMADS only.
|
||||||
|
const nomadsRoot = "https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod"
|
||||||
|
|
||||||
|
type Downloader struct {
|
||||||
|
Dir string
|
||||||
|
Parallel int
|
||||||
|
Client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) fileURL(run string, hour int, step int) string {
|
||||||
|
return fmt.Sprintf("%s/gfs.%s/%02d/atmos/gfs.t%02dz.pgrb2.0p50.f%03d", nomadsRoot, run, hour, hour, step)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) fetch(ctx context.Context, url, dst string) error {
|
||||||
|
if _, err := os.Stat(dst); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tmp := dst + ".part"
|
||||||
|
f, err := os.Create(tmp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
|
resp, err := d.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("bad status %s", resp.Status)
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(f, resp.Body); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Rename(tmp, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) Run(ctx context.Context, run time.Time) error {
|
||||||
|
runStr := run.Format("20060102")
|
||||||
|
hour := run.Hour()
|
||||||
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
|
sem := make(chan struct{}, d.Parallel)
|
||||||
|
for _, step := range steps {
|
||||||
|
step := step
|
||||||
|
sem <- struct{}{}
|
||||||
|
g.Go(func() error {
|
||||||
|
defer func() { <-sem }()
|
||||||
|
url := d.fileURL(runStr, hour, step)
|
||||||
|
dst := filepath.Join(d.Dir, fileName(run, step))
|
||||||
|
return d.fetch(ctx, url, dst)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return g.Wait()
|
||||||
|
}
|
||||||
53
internal/pkg/grib/extractor.go
Normal file
53
internal/pkg/grib/extractor.go
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
func lerp(a, b, t float64) float64 { return a + t*(b-a) }
|
||||||
|
|
||||||
|
// Interpolate 16‑point (time, p, lat, lon)
|
||||||
|
func (d *dataset) uv(lat, lon, alt float64, tHours float64) (float64, float64) {
|
||||||
|
if lon < 0 {
|
||||||
|
lon += 360
|
||||||
|
}
|
||||||
|
iy := (lat + 90) * 2
|
||||||
|
y0 := int(math.Floor(iy))
|
||||||
|
y1 := y0 + 1
|
||||||
|
wy := iy - float64(y0)
|
||||||
|
ix := lon * 2
|
||||||
|
x0 := int(math.Floor(ix)) % d.cube.lon
|
||||||
|
x1 := (x0 + 1) % d.cube.lon
|
||||||
|
wx := ix - float64(x0)
|
||||||
|
it0 := int(math.Floor(tHours / 3.0))
|
||||||
|
wt := (tHours - float64(it0*3)) / 3.0
|
||||||
|
p := pressureFromAlt(alt)
|
||||||
|
ip0 := 0
|
||||||
|
for ip0+1 < len(pressureLevels) && pressureLevels[ip0+1] > p {
|
||||||
|
ip0++
|
||||||
|
}
|
||||||
|
ip1 := ip0 + 1
|
||||||
|
wp := (pressureLevels[ip0] - p) / (pressureLevels[ip0] - pressureLevels[ip1])
|
||||||
|
fetch := func(ti, pi int) (float64, float64) {
|
||||||
|
u00 := d.cube.val(0, ti, pi, y0, x0)
|
||||||
|
u10 := d.cube.val(0, ti, pi, y0, x1)
|
||||||
|
u01 := d.cube.val(0, ti, pi, y1, x0)
|
||||||
|
u11 := d.cube.val(0, ti, pi, y1, x1)
|
||||||
|
v00 := d.cube.val(1, ti, pi, y0, x0)
|
||||||
|
v10 := d.cube.val(1, ti, pi, y0, x1)
|
||||||
|
v01 := d.cube.val(1, ti, pi, y1, x0)
|
||||||
|
v11 := d.cube.val(1, ti, pi, y1, x1)
|
||||||
|
uxy := (1-wy)*((1-wx)*float64(u00)+wx*float64(u10)) + wy*((1-wx)*float64(u01)+wx*float64(u11))
|
||||||
|
vxy := (1-wy)*((1-wx)*float64(v00)+wx*float64(v10)) + wy*((1-wx)*float64(v01)+wx*float64(v11))
|
||||||
|
return uxy, vxy
|
||||||
|
}
|
||||||
|
u0p0, v0p0 := fetch(it0, ip0)
|
||||||
|
u0p1, v0p1 := fetch(it0, ip1)
|
||||||
|
u1p0, v1p0 := fetch(it0+1, ip0)
|
||||||
|
u1p1, v1p1 := fetch(it0+1, ip1)
|
||||||
|
uLow := lerp(u0p0, u0p1, wp)
|
||||||
|
vLow := lerp(v0p0, v0p1, wp)
|
||||||
|
uHig := lerp(u1p0, u1p1, wp)
|
||||||
|
vHig := lerp(v1p0, v1p1, wp)
|
||||||
|
u := lerp(uLow, uHig, wt)
|
||||||
|
v := lerp(vLow, vHig, wt)
|
||||||
|
return u, v
|
||||||
|
}
|
||||||
154
internal/pkg/grib/grib.go
Normal file
154
internal/pkg/grib/grib.go
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/errcodes"
|
||||||
|
"github.com/edsrzf/mmap-go"
|
||||||
|
"github.com/nilsmagnus/grib/griblib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RedisIface interface {
|
||||||
|
Lock(ctx context.Context, key string, ttl time.Duration) (func(context.Context), error)
|
||||||
|
Set(key string, value []byte, ttl time.Duration) error
|
||||||
|
Get(key string) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceConfig struct {
|
||||||
|
Dir string
|
||||||
|
TTL time.Duration
|
||||||
|
CacheTTL time.Duration
|
||||||
|
Redis RedisIface
|
||||||
|
Parallel int
|
||||||
|
Client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
cfg ServiceConfig
|
||||||
|
cache memCache
|
||||||
|
data atomic.Pointer[dataset]
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cfg ServiceConfig) (*service, error) {
|
||||||
|
if cfg.TTL == 0 {
|
||||||
|
cfg.TTL = 24 * time.Hour
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(cfg.Dir, 0o755); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s := &service{cfg: cfg, cache: memCache{ttl: cfg.CacheTTL}}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update() downloads missing GRIBs, assembles cube into a single mmap‑file.
|
||||||
|
func (s *service) Update(ctx context.Context) error {
|
||||||
|
unlock, err := s.cfg.Redis.Lock(ctx, "grib-dl", 45*time.Minute)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer unlock(ctx)
|
||||||
|
|
||||||
|
dl := downloader.Downloader{Dir: s.cfg.Dir, Parallel: s.cfg.Parallel, Client: s.cfg.Client}
|
||||||
|
run := nearestRun(time.Now().UTC().Add(-4 * time.Hour))
|
||||||
|
if err := dl.Run(ctx, run); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cubePath := filepath.Join(s.cfg.Dir, run.Format("20060102_15")) + ".cube"
|
||||||
|
if _, err := os.Stat(cubePath); err != nil {
|
||||||
|
if err := assembleCube(s.cfg.Dir, run, cubePath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c, err := openCube(cubePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ds := &dataset{cube: c, runUTC: run.Unix()}
|
||||||
|
s.data.Store(ds)
|
||||||
|
s.cache = memCache{ttl: s.cfg.CacheTTL}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func assembleCube(dir string, run time.Time, cubePath string) error {
|
||||||
|
const sizePerVar = 17 * 34 * 361 * 720 * 4
|
||||||
|
total := int64(sizePerVar * 2)
|
||||||
|
f, err := os.Create(cubePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := f.Truncate(total); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mm, err := mmap.MapRegion(f, int(total), mmap.RDWR, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer mm.Unmap()
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
pIndex := make(map[int]int)
|
||||||
|
for i, p := range pressureLevels {
|
||||||
|
pIndex[int(math.Round(p))] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
for ti, step := range steps {
|
||||||
|
fn := filepath.Join(dir, fileName(run, step))
|
||||||
|
gf, err := griblib.Read(fn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, m := range gf.Messages {
|
||||||
|
if m.ParameterShortName != "u" && m.ParameterShortName != "v" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m.TypeOfFirstFixedSurface != 100 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pIdx, ok := pIndex[int(m.PressureLevel)]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
varIdx := 0
|
||||||
|
if m.ParameterShortName == "v" {
|
||||||
|
varIdx = 1
|
||||||
|
}
|
||||||
|
vals := m.Values
|
||||||
|
// GRIB library returns scan north->south, west->east already in row-major order
|
||||||
|
raw := make([]byte, len(vals)*4)
|
||||||
|
for i, v := range vals {
|
||||||
|
binary.LittleEndian.PutUint32(raw[i*4:], math.Float32bits(float32(v)))
|
||||||
|
}
|
||||||
|
base := int64(varIdx*sizePerVar + (ti*34+pIdx)*361*720*4)
|
||||||
|
copy(mm[base:base+int64(len(raw))], raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mm.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Extract(ctx context.Context, lat, lon, alt float64, ts time.Time) ([2]float64, error) {
|
||||||
|
var zero [2]float64
|
||||||
|
d := s.data.Load()
|
||||||
|
if d == nil {
|
||||||
|
return zero, errcodes.ErrNoDataset
|
||||||
|
}
|
||||||
|
if ts.Before(time.Unix(d.runUTC, 0)) || ts.After(time.Unix(d.runUTC, 0).Add(48*time.Hour)) {
|
||||||
|
return zero, errcodes.ErrOutOfBounds
|
||||||
|
}
|
||||||
|
key := encodeKey(lat, lon, alt, ts)
|
||||||
|
if v, ok := s.cache.get(key); ok {
|
||||||
|
return [2]float64(v), nil
|
||||||
|
}
|
||||||
|
td := ts.Sub(time.Unix(d.runUTC, 0)).Hours()
|
||||||
|
u, v := d.uv(lat, lon, alt, td)
|
||||||
|
out := [2]float64{u, v}
|
||||||
|
s.cache.set(key, vec(out))
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
9
internal/pkg/grib/pressure.go
Normal file
9
internal/pkg/grib/pressure.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
var pressureLevels = []float64{1000, 975, 950, 925, 900, 875, 850, 825, 800, 775, 750, 725, 700, 650, 600, 550, 500, 450, 400, 350, 300, 250, 200, 150, 100, 70, 50, 30, 20, 10, 7, 5, 3, 2}
|
||||||
|
|
||||||
|
func pressureFromAlt(alt float64) float64 { // ICAO ISA
|
||||||
|
return 1013.25 * math.Pow(1-alt/44307.69396, 5.255877)
|
||||||
|
}
|
||||||
26
internal/pkg/grib/util.go
Normal file
26
internal/pkg/grib/util.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package grib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var steps = []int{0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48}
|
||||||
|
|
||||||
|
func nearestRun(t time.Time) time.Time {
|
||||||
|
h := t.UTC().Hour() - t.UTC().Hour()%6
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day(), h, 0, 0, 0, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileName(run time.Time, step int) string {
|
||||||
|
return fmt.Sprintf("gfs.t%02dz.pgrb2.0p50.f%03d", run.Hour(), step)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeKey(a ...any) uint64 {
|
||||||
|
h := fnv.New64a()
|
||||||
|
for _, v := range a {
|
||||||
|
fmt.Fprint(h, v)
|
||||||
|
}
|
||||||
|
return h.Sum64()
|
||||||
|
}
|
||||||
23
internal/pkg/log/log.go
Normal file
23
internal/pkg/log/log.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ctxLogKey struct{}
|
||||||
|
|
||||||
|
func ToCtx(ctx context.Context, lg *zap.Logger) context.Context {
|
||||||
|
return context.WithValue(ctx, ctxLogKey{}, lg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ctx(ctx context.Context) *zap.Logger {
|
||||||
|
lg, ok := ctx.Value(ctxLogKey{}).(*zap.Logger)
|
||||||
|
if !ok || lg == nil {
|
||||||
|
zap.L().Error("no logger in context, using global")
|
||||||
|
return zap.L()
|
||||||
|
}
|
||||||
|
|
||||||
|
return lg
|
||||||
|
}
|
||||||
16
internal/service/deps.go
Normal file
16
internal/service/deps.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Redis interface {
|
||||||
|
Lock(ctx context.Context, key string, ttl time.Duration) (func(context.Context), error)
|
||||||
|
Set(key string, value []byte, ttl time.Duration) error
|
||||||
|
Get(key string) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Grib interface {
|
||||||
|
Update(ctx context.Context) error
|
||||||
|
}
|
||||||
13
internal/service/predictor.go
Normal file
13
internal/service/predictor.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/ds"
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/errcodes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Service) PerformPrediction(ctx context.Context, params ds.PredictionParameters) ([]ds.PredicitonResult, error) {
|
||||||
|
return nil, errcodes.New(http.StatusNotImplemented, "not implemented", "please wait")
|
||||||
|
}
|
||||||
22
internal/service/service.go
Normal file
22
internal/service/service.go
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
redis Redis
|
||||||
|
downloader Downloader
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(redis Redis, downloader Downloader) *Service {
|
||||||
|
return &Service{
|
||||||
|
redis: redis,
|
||||||
|
downloader: downloader,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadWeatherData downloads weather forecast data using the configured downloader
|
||||||
|
func (s *Service) DownloadWeatherData(ctx context.Context) error {
|
||||||
|
return s.downloader.Download(ctx)
|
||||||
|
}
|
||||||
44
internal/transport/middleware/log.go
Normal file
44
internal/transport/middleware/log.go
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/errcodes"
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/log"
|
||||||
|
"github.com/ogen-go/ogen/middleware"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Logging(logger *zap.Logger) middleware.Middleware {
|
||||||
|
return func(req middleware.Request, next func(req middleware.Request) (middleware.Response, error)) (middleware.Response, error) {
|
||||||
|
lg := logger.With(
|
||||||
|
zap.String("operationId", req.OperationID),
|
||||||
|
)
|
||||||
|
|
||||||
|
lg.Info("started request")
|
||||||
|
|
||||||
|
req.Context = log.ToCtx(req.Context, lg)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
resp, err := next(req)
|
||||||
|
dur := time.Since(start).Microseconds()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if errcode, ok := err.(*errcodes.ErrorCode); ok {
|
||||||
|
lg.Error("request error",
|
||||||
|
zap.Int("status_code", errcode.StatusCode),
|
||||||
|
zap.String("message", errcode.Message),
|
||||||
|
zap.String("details", errcode.Details),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
lg.Error("request internal error",
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lg.Info("done request", zap.Float64("duration_ms", float64(dur)/float64(1000)))
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
23
internal/transport/rest/config.go
Normal file
23
internal/transport/rest/config.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
env "github.com/caarlos0/env/v11"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Port int `env:"PORT" envDefault:"8080"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig(servicePrefix string) (*Config, error) {
|
||||||
|
cfg := &Config{}
|
||||||
|
|
||||||
|
if err := env.ParseWithOptions(cfg, env.Options{
|
||||||
|
PrefixTagName: fmt.Sprintf("%s_REST_", servicePrefix),
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
11
internal/transport/rest/handler/deps.go
Normal file
11
internal/transport/rest/handler/deps.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/ds"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Service interface {
|
||||||
|
PerformPrediction(ctx context.Context, params ds.PredictionParameters) ([]ds.PredicitonResult, error)
|
||||||
|
}
|
||||||
52
internal/transport/rest/handler/handler.go
Normal file
52
internal/transport/rest/handler/handler.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/pkg/errcodes"
|
||||||
|
api "git.intra.yksa.space/gsn/predictor/pkg/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ api.Handler = (*Handler)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
svc Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(svc Service) *Handler {
|
||||||
|
return &Handler{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) PerformPrediction(ctx context.Context, req api.OptPredictionParameters, params api.PerformPredictionParams) (*api.PredictionResult, error) {
|
||||||
|
return nil, errcodes.New(http.StatusNotImplemented, "not implemented", "please wait")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) NewError(ctx context.Context, err error) *api.ErrorStatusCode {
|
||||||
|
if errcode, ok := err.(*errcodes.ErrorCode); ok {
|
||||||
|
resp := api.Error{
|
||||||
|
Message: errcode.Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
if errcode.Details != "" {
|
||||||
|
resp.Details = api.NewOptString(errcode.Details)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.ErrorStatusCode{
|
||||||
|
StatusCode: errcode.StatusCode,
|
||||||
|
Response: resp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.ErrorStatusCode{
|
||||||
|
StatusCode: http.StatusInternalServerError,
|
||||||
|
Response: api.Error{
|
||||||
|
Message: "undefined internal error",
|
||||||
|
Details: api.NewOptString(err.Error()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
38
internal/transport/rest/transport.go
Normal file
38
internal/transport/rest/transport.go
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.intra.yksa.space/gsn/predictor/internal/transport/middleware"
|
||||||
|
handler "git.intra.yksa.space/gsn/predictor/internal/transport/rest/handler"
|
||||||
|
api "git.intra.yksa.space/gsn/predictor/pkg/rest"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Transport struct {
|
||||||
|
lg *zap.Logger
|
||||||
|
cfg *Config
|
||||||
|
srv *api.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lg *zap.Logger, handler *handler.Handler, cfg *Config) (*Transport, error) {
|
||||||
|
srv, err := api.NewServer(handler, api.WithMiddleware(middleware.Logging(lg)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Transport{
|
||||||
|
lg: lg,
|
||||||
|
srv: srv,
|
||||||
|
cfg: cfg,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Transport) Run() {
|
||||||
|
t.lg.Info("started")
|
||||||
|
|
||||||
|
if err := http.ListenAndServe(fmt.Sprintf(":%d", t.cfg.Port), t.srv); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
283
pkg/rest/oas_cfg_gen.go
Normal file
283
pkg/rest/oas_cfg_gen.go
Normal file
|
|
@ -0,0 +1,283 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
"github.com/ogen-go/ogen/middleware"
|
||||||
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/otelogen"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Allocate option closure once.
|
||||||
|
clientSpanKind = trace.WithSpanKind(trace.SpanKindClient)
|
||||||
|
// Allocate option closure once.
|
||||||
|
serverSpanKind = trace.WithSpanKind(trace.SpanKindServer)
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
optionFunc[C any] func(*C)
|
||||||
|
otelOptionFunc func(*otelConfig)
|
||||||
|
)
|
||||||
|
|
||||||
|
type otelConfig struct {
|
||||||
|
TracerProvider trace.TracerProvider
|
||||||
|
Tracer trace.Tracer
|
||||||
|
MeterProvider metric.MeterProvider
|
||||||
|
Meter metric.Meter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *otelConfig) initOTEL() {
|
||||||
|
if cfg.TracerProvider == nil {
|
||||||
|
cfg.TracerProvider = otel.GetTracerProvider()
|
||||||
|
}
|
||||||
|
if cfg.MeterProvider == nil {
|
||||||
|
cfg.MeterProvider = otel.GetMeterProvider()
|
||||||
|
}
|
||||||
|
cfg.Tracer = cfg.TracerProvider.Tracer(otelogen.Name,
|
||||||
|
trace.WithInstrumentationVersion(otelogen.SemVersion()),
|
||||||
|
)
|
||||||
|
cfg.Meter = cfg.MeterProvider.Meter(otelogen.Name,
|
||||||
|
metric.WithInstrumentationVersion(otelogen.SemVersion()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorHandler is error handler.
|
||||||
|
type ErrorHandler = ogenerrors.ErrorHandler
|
||||||
|
|
||||||
|
type serverConfig struct {
|
||||||
|
otelConfig
|
||||||
|
NotFound http.HandlerFunc
|
||||||
|
MethodNotAllowed func(w http.ResponseWriter, r *http.Request, allowed string)
|
||||||
|
ErrorHandler ErrorHandler
|
||||||
|
Prefix string
|
||||||
|
Middleware Middleware
|
||||||
|
MaxMultipartMemory int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerOption is server config option.
|
||||||
|
type ServerOption interface {
|
||||||
|
applyServer(*serverConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ServerOption = (optionFunc[serverConfig])(nil)
|
||||||
|
|
||||||
|
func (o optionFunc[C]) applyServer(c *C) {
|
||||||
|
o(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ServerOption = (otelOptionFunc)(nil)
|
||||||
|
|
||||||
|
func (o otelOptionFunc) applyServer(c *serverConfig) {
|
||||||
|
o(&c.otelConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newServerConfig(opts ...ServerOption) serverConfig {
|
||||||
|
cfg := serverConfig{
|
||||||
|
NotFound: http.NotFound,
|
||||||
|
MethodNotAllowed: func(w http.ResponseWriter, r *http.Request, allowed string) {
|
||||||
|
status := http.StatusMethodNotAllowed
|
||||||
|
if r.Method == "OPTIONS" {
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", allowed)
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||||
|
status = http.StatusNoContent
|
||||||
|
} else {
|
||||||
|
w.Header().Set("Allow", allowed)
|
||||||
|
}
|
||||||
|
w.WriteHeader(status)
|
||||||
|
},
|
||||||
|
ErrorHandler: ogenerrors.DefaultErrorHandler,
|
||||||
|
Middleware: nil,
|
||||||
|
MaxMultipartMemory: 32 << 20, // 32 MB
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.applyServer(&cfg)
|
||||||
|
}
|
||||||
|
cfg.initOTEL()
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type baseServer struct {
|
||||||
|
cfg serverConfig
|
||||||
|
requests metric.Int64Counter
|
||||||
|
errors metric.Int64Counter
|
||||||
|
duration metric.Float64Histogram
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s baseServer) notFound(w http.ResponseWriter, r *http.Request) {
|
||||||
|
s.cfg.NotFound(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s baseServer) notAllowed(w http.ResponseWriter, r *http.Request, allowed string) {
|
||||||
|
s.cfg.MethodNotAllowed(w, r, allowed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg serverConfig) baseServer() (s baseServer, err error) {
|
||||||
|
s = baseServer{cfg: cfg}
|
||||||
|
if s.requests, err = otelogen.ServerRequestCountCounter(s.cfg.Meter); err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
if s.errors, err = otelogen.ServerErrorsCountCounter(s.cfg.Meter); err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
if s.duration, err = otelogen.ServerDurationHistogram(s.cfg.Meter); err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientConfig struct {
|
||||||
|
otelConfig
|
||||||
|
Client ht.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientOption is client config option.
|
||||||
|
type ClientOption interface {
|
||||||
|
applyClient(*clientConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ClientOption = (optionFunc[clientConfig])(nil)
|
||||||
|
|
||||||
|
func (o optionFunc[C]) applyClient(c *C) {
|
||||||
|
o(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ClientOption = (otelOptionFunc)(nil)
|
||||||
|
|
||||||
|
func (o otelOptionFunc) applyClient(c *clientConfig) {
|
||||||
|
o(&c.otelConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClientConfig(opts ...ClientOption) clientConfig {
|
||||||
|
cfg := clientConfig{
|
||||||
|
Client: http.DefaultClient,
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.applyClient(&cfg)
|
||||||
|
}
|
||||||
|
cfg.initOTEL()
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type baseClient struct {
|
||||||
|
cfg clientConfig
|
||||||
|
requests metric.Int64Counter
|
||||||
|
errors metric.Int64Counter
|
||||||
|
duration metric.Float64Histogram
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg clientConfig) baseClient() (c baseClient, err error) {
|
||||||
|
c = baseClient{cfg: cfg}
|
||||||
|
if c.requests, err = otelogen.ClientRequestCountCounter(c.cfg.Meter); err != nil {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
if c.errors, err = otelogen.ClientErrorsCountCounter(c.cfg.Meter); err != nil {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
if c.duration, err = otelogen.ClientDurationHistogram(c.cfg.Meter); err != nil {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option is config option.
|
||||||
|
type Option interface {
|
||||||
|
ServerOption
|
||||||
|
ClientOption
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTracerProvider specifies a tracer provider to use for creating a tracer.
|
||||||
|
//
|
||||||
|
// If none is specified, the global provider is used.
|
||||||
|
func WithTracerProvider(provider trace.TracerProvider) Option {
|
||||||
|
return otelOptionFunc(func(cfg *otelConfig) {
|
||||||
|
if provider != nil {
|
||||||
|
cfg.TracerProvider = provider
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMeterProvider specifies a meter provider to use for creating a meter.
|
||||||
|
//
|
||||||
|
// If none is specified, the otel.GetMeterProvider() is used.
|
||||||
|
func WithMeterProvider(provider metric.MeterProvider) Option {
|
||||||
|
return otelOptionFunc(func(cfg *otelConfig) {
|
||||||
|
if provider != nil {
|
||||||
|
cfg.MeterProvider = provider
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithClient specifies http client to use.
|
||||||
|
func WithClient(client ht.Client) ClientOption {
|
||||||
|
return optionFunc[clientConfig](func(cfg *clientConfig) {
|
||||||
|
if client != nil {
|
||||||
|
cfg.Client = client
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNotFound specifies Not Found handler to use.
|
||||||
|
func WithNotFound(notFound http.HandlerFunc) ServerOption {
|
||||||
|
return optionFunc[serverConfig](func(cfg *serverConfig) {
|
||||||
|
if notFound != nil {
|
||||||
|
cfg.NotFound = notFound
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMethodNotAllowed specifies Method Not Allowed handler to use.
|
||||||
|
func WithMethodNotAllowed(methodNotAllowed func(w http.ResponseWriter, r *http.Request, allowed string)) ServerOption {
|
||||||
|
return optionFunc[serverConfig](func(cfg *serverConfig) {
|
||||||
|
if methodNotAllowed != nil {
|
||||||
|
cfg.MethodNotAllowed = methodNotAllowed
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithErrorHandler specifies error handler to use.
|
||||||
|
func WithErrorHandler(h ErrorHandler) ServerOption {
|
||||||
|
return optionFunc[serverConfig](func(cfg *serverConfig) {
|
||||||
|
if h != nil {
|
||||||
|
cfg.ErrorHandler = h
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPathPrefix specifies server path prefix.
|
||||||
|
func WithPathPrefix(prefix string) ServerOption {
|
||||||
|
return optionFunc[serverConfig](func(cfg *serverConfig) {
|
||||||
|
cfg.Prefix = prefix
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMiddleware specifies middlewares to use.
|
||||||
|
func WithMiddleware(m ...Middleware) ServerOption {
|
||||||
|
return optionFunc[serverConfig](func(cfg *serverConfig) {
|
||||||
|
switch len(m) {
|
||||||
|
case 0:
|
||||||
|
cfg.Middleware = nil
|
||||||
|
case 1:
|
||||||
|
cfg.Middleware = m[0]
|
||||||
|
default:
|
||||||
|
cfg.Middleware = middleware.ChainMiddlewares(m...)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxMultipartMemory specifies limit of memory for storing file parts.
|
||||||
|
// File parts which can't be stored in memory will be stored on disk in temporary files.
|
||||||
|
func WithMaxMultipartMemory(max int64) ServerOption {
|
||||||
|
return optionFunc[serverConfig](func(cfg *serverConfig) {
|
||||||
|
if max > 0 {
|
||||||
|
cfg.MaxMultipartMemory = max
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
179
pkg/rest/oas_client_gen.go
Normal file
179
pkg/rest/oas_client_gen.go
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
"github.com/ogen-go/ogen/otelogen"
|
||||||
|
"github.com/ogen-go/ogen/uri"
|
||||||
|
)
|
||||||
|
|
||||||
|
func trimTrailingSlashes(u *url.URL) {
|
||||||
|
u.Path = strings.TrimRight(u.Path, "/")
|
||||||
|
u.RawPath = strings.TrimRight(u.RawPath, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoker invokes operations described by OpenAPI v3 specification.
|
||||||
|
type Invoker interface {
|
||||||
|
// PerformPrediction invokes performPrediction operation.
|
||||||
|
//
|
||||||
|
// Perform preidction.
|
||||||
|
//
|
||||||
|
// POST /api/v1/prediction
|
||||||
|
PerformPrediction(ctx context.Context, request OptPredictionParameters, params PerformPredictionParams) (*PredictionResult, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client implements OAS client.
|
||||||
|
type Client struct {
|
||||||
|
serverURL *url.URL
|
||||||
|
baseClient
|
||||||
|
}
|
||||||
|
type errorHandler interface {
|
||||||
|
NewError(ctx context.Context, err error) *ErrorStatusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Handler = struct {
|
||||||
|
errorHandler
|
||||||
|
*Client
|
||||||
|
}{}
|
||||||
|
|
||||||
|
// NewClient initializes new Client defined by OAS.
|
||||||
|
func NewClient(serverURL string, opts ...ClientOption) (*Client, error) {
|
||||||
|
u, err := url.Parse(serverURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
trimTrailingSlashes(u)
|
||||||
|
|
||||||
|
c, err := newClientConfig(opts...).baseClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
serverURL: u,
|
||||||
|
baseClient: c,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverURLKey struct{}
|
||||||
|
|
||||||
|
// WithServerURL sets context key to override server URL.
|
||||||
|
func WithServerURL(ctx context.Context, u *url.URL) context.Context {
|
||||||
|
return context.WithValue(ctx, serverURLKey{}, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) requestURL(ctx context.Context) *url.URL {
|
||||||
|
u, ok := ctx.Value(serverURLKey{}).(*url.URL)
|
||||||
|
if !ok {
|
||||||
|
return c.serverURL
|
||||||
|
}
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// PerformPrediction invokes performPrediction operation.
|
||||||
|
//
|
||||||
|
// Perform preidction.
|
||||||
|
//
|
||||||
|
// POST /api/v1/prediction
|
||||||
|
func (c *Client) PerformPrediction(ctx context.Context, request OptPredictionParameters, params PerformPredictionParams) (*PredictionResult, error) {
|
||||||
|
res, err := c.sendPerformPrediction(ctx, request, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) sendPerformPrediction(ctx context.Context, request OptPredictionParameters, params PerformPredictionParams) (res *PredictionResult, err error) {
|
||||||
|
otelAttrs := []attribute.KeyValue{
|
||||||
|
otelogen.OperationID("performPrediction"),
|
||||||
|
semconv.HTTPRequestMethodKey.String("POST"),
|
||||||
|
semconv.HTTPRouteKey.String("/api/v1/prediction"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run stopwatch.
|
||||||
|
startTime := time.Now()
|
||||||
|
defer func() {
|
||||||
|
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||||
|
elapsedDuration := time.Since(startTime)
|
||||||
|
c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...))
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Increment request counter.
|
||||||
|
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||||
|
|
||||||
|
// Start a span for this request.
|
||||||
|
ctx, span := c.cfg.Tracer.Start(ctx, PerformPredictionOperation,
|
||||||
|
trace.WithAttributes(otelAttrs...),
|
||||||
|
clientSpanKind,
|
||||||
|
)
|
||||||
|
// Track stage for error reporting.
|
||||||
|
var stage string
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, stage)
|
||||||
|
c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||||
|
}
|
||||||
|
span.End()
|
||||||
|
}()
|
||||||
|
|
||||||
|
stage = "BuildURL"
|
||||||
|
u := uri.Clone(c.requestURL(ctx))
|
||||||
|
var pathParts [1]string
|
||||||
|
pathParts[0] = "/api/v1/prediction"
|
||||||
|
uri.AddPathParts(u, pathParts[:]...)
|
||||||
|
|
||||||
|
stage = "EncodeQueryParams"
|
||||||
|
q := uri.NewQueryEncoder()
|
||||||
|
{
|
||||||
|
// Encode "parameters" parameter.
|
||||||
|
cfg := uri.QueryParameterEncodingConfig{
|
||||||
|
Name: "parameters",
|
||||||
|
Style: uri.QueryStyleForm,
|
||||||
|
Explode: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
|
||||||
|
if val, ok := params.Parameters.Get(); ok {
|
||||||
|
return val.EncodeURI(e)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return res, errors.Wrap(err, "encode query")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Values().Encode()
|
||||||
|
|
||||||
|
stage = "EncodeRequest"
|
||||||
|
r, err := ht.NewRequest(ctx, "POST", u)
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "create request")
|
||||||
|
}
|
||||||
|
if err := encodePerformPredictionRequest(request, r); err != nil {
|
||||||
|
return res, errors.Wrap(err, "encode request")
|
||||||
|
}
|
||||||
|
|
||||||
|
stage = "SendRequest"
|
||||||
|
resp, err := c.cfg.Client.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "do request")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
stage = "DecodeResponse"
|
||||||
|
result, err := decodePerformPredictionResponse(resp)
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "decode response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
15
pkg/rest/oas_defaults_gen.go
Normal file
15
pkg/rest/oas_defaults_gen.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
// setDefaults set default value of fields.
|
||||||
|
func (s *PredictionParameters) setDefaults() {
|
||||||
|
{
|
||||||
|
val := bool(false)
|
||||||
|
s.Interpolate.SetTo(val)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
val := PredictionParametersFormat("json")
|
||||||
|
s.Format.SetTo(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
195
pkg/rest/oas_handlers_gen.go
Normal file
195
pkg/rest/oas_handlers_gen.go
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
"github.com/ogen-go/ogen/middleware"
|
||||||
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/otelogen"
|
||||||
|
)
|
||||||
|
|
||||||
|
type codeRecorder struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
status int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *codeRecorder) WriteHeader(status int) {
|
||||||
|
c.status = status
|
||||||
|
c.ResponseWriter.WriteHeader(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlePerformPredictionRequest handles performPrediction operation.
|
||||||
|
//
|
||||||
|
// Perform preidction.
|
||||||
|
//
|
||||||
|
// POST /api/v1/prediction
|
||||||
|
func (s *Server) handlePerformPredictionRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||||
|
statusWriter := &codeRecorder{ResponseWriter: w}
|
||||||
|
w = statusWriter
|
||||||
|
otelAttrs := []attribute.KeyValue{
|
||||||
|
otelogen.OperationID("performPrediction"),
|
||||||
|
semconv.HTTPRequestMethodKey.String("POST"),
|
||||||
|
semconv.HTTPRouteKey.String("/api/v1/prediction"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a span for this request.
|
||||||
|
ctx, span := s.cfg.Tracer.Start(r.Context(), PerformPredictionOperation,
|
||||||
|
trace.WithAttributes(otelAttrs...),
|
||||||
|
serverSpanKind,
|
||||||
|
)
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
// Add Labeler to context.
|
||||||
|
labeler := &Labeler{attrs: otelAttrs}
|
||||||
|
ctx = contextWithLabeler(ctx, labeler)
|
||||||
|
|
||||||
|
// Run stopwatch.
|
||||||
|
startTime := time.Now()
|
||||||
|
defer func() {
|
||||||
|
elapsedDuration := time.Since(startTime)
|
||||||
|
|
||||||
|
attrSet := labeler.AttributeSet()
|
||||||
|
attrs := attrSet.ToSlice()
|
||||||
|
code := statusWriter.status
|
||||||
|
if code != 0 {
|
||||||
|
codeAttr := semconv.HTTPResponseStatusCode(code)
|
||||||
|
attrs = append(attrs, codeAttr)
|
||||||
|
span.SetAttributes(codeAttr)
|
||||||
|
}
|
||||||
|
attrOpt := metric.WithAttributes(attrs...)
|
||||||
|
|
||||||
|
// Increment request counter.
|
||||||
|
s.requests.Add(ctx, 1, attrOpt)
|
||||||
|
|
||||||
|
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||||
|
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
|
||||||
|
}()
|
||||||
|
|
||||||
|
var (
|
||||||
|
recordError = func(stage string, err error) {
|
||||||
|
span.RecordError(err)
|
||||||
|
|
||||||
|
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
|
||||||
|
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
|
||||||
|
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
|
||||||
|
// max redirects exceeded), in which case status MUST be set to Error.
|
||||||
|
code := statusWriter.status
|
||||||
|
if code >= 100 && code < 500 {
|
||||||
|
span.SetStatus(codes.Error, stage)
|
||||||
|
}
|
||||||
|
|
||||||
|
attrSet := labeler.AttributeSet()
|
||||||
|
attrs := attrSet.ToSlice()
|
||||||
|
if code != 0 {
|
||||||
|
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
|
||||||
|
}
|
||||||
|
err error
|
||||||
|
opErrContext = ogenerrors.OperationContext{
|
||||||
|
Name: PerformPredictionOperation,
|
||||||
|
ID: "performPrediction",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
params, err := decodePerformPredictionParams(args, argsEscaped, r)
|
||||||
|
if err != nil {
|
||||||
|
err = &ogenerrors.DecodeParamsError{
|
||||||
|
OperationContext: opErrContext,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
defer recordError("DecodeParams", err)
|
||||||
|
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request, close, err := s.decodePerformPredictionRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
err = &ogenerrors.DecodeRequestError{
|
||||||
|
OperationContext: opErrContext,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
defer recordError("DecodeRequest", err)
|
||||||
|
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := close(); err != nil {
|
||||||
|
recordError("CloseRequest", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var response *PredictionResult
|
||||||
|
if m := s.cfg.Middleware; m != nil {
|
||||||
|
mreq := middleware.Request{
|
||||||
|
Context: ctx,
|
||||||
|
OperationName: PerformPredictionOperation,
|
||||||
|
OperationSummary: "Perform preidction",
|
||||||
|
OperationID: "performPrediction",
|
||||||
|
Body: request,
|
||||||
|
Params: middleware.Parameters{
|
||||||
|
{
|
||||||
|
Name: "parameters",
|
||||||
|
In: "query",
|
||||||
|
}: params.Parameters,
|
||||||
|
},
|
||||||
|
Raw: r,
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
Request = OptPredictionParameters
|
||||||
|
Params = PerformPredictionParams
|
||||||
|
Response = *PredictionResult
|
||||||
|
)
|
||||||
|
response, err = middleware.HookMiddleware[
|
||||||
|
Request,
|
||||||
|
Params,
|
||||||
|
Response,
|
||||||
|
](
|
||||||
|
m,
|
||||||
|
mreq,
|
||||||
|
unpackPerformPredictionParams,
|
||||||
|
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
||||||
|
response, err = s.h.PerformPrediction(ctx, request, params)
|
||||||
|
return response, err
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
response, err = s.h.PerformPrediction(ctx, request, params)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if errRes, ok := errors.Into[*ErrorStatusCode](err); ok {
|
||||||
|
if err := encodeErrorResponse(errRes, w, span); err != nil {
|
||||||
|
defer recordError("Internal", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if errors.Is(err, ht.ErrNotImplemented) {
|
||||||
|
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil {
|
||||||
|
defer recordError("Internal", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := encodePerformPredictionResponse(response, w, span); err != nil {
|
||||||
|
defer recordError("EncodeResponse", err)
|
||||||
|
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
||||||
|
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
1190
pkg/rest/oas_json_gen.go
Normal file
1190
pkg/rest/oas_json_gen.go
Normal file
File diff suppressed because it is too large
Load diff
42
pkg/rest/oas_labeler_gen.go
Normal file
42
pkg/rest/oas_labeler_gen.go
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Labeler is used to allow adding custom attributes to the server request metrics.
|
||||||
|
type Labeler struct {
|
||||||
|
attrs []attribute.KeyValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add attributes to the Labeler.
|
||||||
|
func (l *Labeler) Add(attrs ...attribute.KeyValue) {
|
||||||
|
l.attrs = append(l.attrs, attrs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttributeSet returns the attributes added to the Labeler as an attribute.Set.
|
||||||
|
func (l *Labeler) AttributeSet() attribute.Set {
|
||||||
|
return attribute.NewSet(l.attrs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type labelerContextKey struct{}
|
||||||
|
|
||||||
|
// LabelerFromContext retrieves the Labeler from the provided context, if present.
|
||||||
|
//
|
||||||
|
// If no Labeler was found in the provided context a new, empty Labeler is returned and the second
|
||||||
|
// return value is false. In this case it is safe to use the Labeler but any attributes added to
|
||||||
|
// it will not be used.
|
||||||
|
func LabelerFromContext(ctx context.Context) (*Labeler, bool) {
|
||||||
|
if l, ok := ctx.Value(labelerContextKey{}).(*Labeler); ok {
|
||||||
|
return l, true
|
||||||
|
}
|
||||||
|
return &Labeler{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func contextWithLabeler(ctx context.Context, l *Labeler) context.Context {
|
||||||
|
return context.WithValue(ctx, labelerContextKey{}, l)
|
||||||
|
}
|
||||||
10
pkg/rest/oas_middleware_gen.go
Normal file
10
pkg/rest/oas_middleware_gen.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ogen-go/ogen/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Middleware is middleware type.
|
||||||
|
type Middleware = middleware.Middleware
|
||||||
10
pkg/rest/oas_operations_gen.go
Normal file
10
pkg/rest/oas_operations_gen.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
// OperationName is the ogen operation name
|
||||||
|
type OperationName = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PerformPredictionOperation OperationName = "PerformPrediction"
|
||||||
|
)
|
||||||
80
pkg/rest/oas_parameters_gen.go
Normal file
80
pkg/rest/oas_parameters_gen.go
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ogen-go/ogen/middleware"
|
||||||
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/uri"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PerformPredictionParams is parameters of performPrediction operation.
|
||||||
|
type PerformPredictionParams struct {
|
||||||
|
Parameters OptPredictionParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackPerformPredictionParams(packed middleware.Parameters) (params PerformPredictionParams) {
|
||||||
|
{
|
||||||
|
key := middleware.ParameterKey{
|
||||||
|
Name: "parameters",
|
||||||
|
In: "query",
|
||||||
|
}
|
||||||
|
if v, ok := packed[key]; ok {
|
||||||
|
params.Parameters = v.(OptPredictionParameters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodePerformPredictionParams(args [0]string, argsEscaped bool, r *http.Request) (params PerformPredictionParams, _ error) {
|
||||||
|
q := uri.NewQueryDecoder(r.URL.Query())
|
||||||
|
// Decode query: parameters.
|
||||||
|
if err := func() error {
|
||||||
|
cfg := uri.QueryParameterDecodingConfig{
|
||||||
|
Name: "parameters",
|
||||||
|
Style: uri.QueryStyleForm,
|
||||||
|
Explode: true,
|
||||||
|
Fields: []uri.QueryParameterObjectField{{Name: "launch_latitude", Required: false}, {Name: "launch_longitude", Required: false}, {Name: "launch_datetime", Required: false}, {Name: "launch_altitude", Required: false}, {Name: "profile", Required: false}, {Name: "ascent_rate", Required: false}, {Name: "burst_altitude", Required: false}, {Name: "descent_rate", Required: false}, {Name: "float_altitude", Required: false}, {Name: "stop_datetime", Required: false}, {Name: "ascent_curve", Required: false}, {Name: "descent_curve", Required: false}, {Name: "interpolate", Required: false}, {Name: "format", Required: false}, {Name: "dataset", Required: false}},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.HasParam(cfg); err == nil {
|
||||||
|
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
|
||||||
|
var paramsDotParametersVal PredictionParameters
|
||||||
|
if err := func() error {
|
||||||
|
return paramsDotParametersVal.DecodeURI(d)
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
params.Parameters.SetTo(paramsDotParametersVal)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := params.Parameters.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := value.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return params, &ogenerrors.DecodeParamError{
|
||||||
|
Name: "parameters",
|
||||||
|
In: "query",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
97
pkg/rest/oas_request_decoders_gen.go
Normal file
97
pkg/rest/oas_request_decoders_gen.go
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"mime"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
"github.com/go-faster/jx"
|
||||||
|
|
||||||
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) decodePerformPredictionRequest(r *http.Request) (
|
||||||
|
req OptPredictionParameters,
|
||||||
|
close func() error,
|
||||||
|
rerr error,
|
||||||
|
) {
|
||||||
|
var closers []func() error
|
||||||
|
close = func() error {
|
||||||
|
var merr error
|
||||||
|
// Close in reverse order, to match defer behavior.
|
||||||
|
for i := len(closers) - 1; i >= 0; i-- {
|
||||||
|
c := closers[i]
|
||||||
|
merr = errors.Join(merr, c())
|
||||||
|
}
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if rerr != nil {
|
||||||
|
rerr = errors.Join(rerr, close())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if _, ok := r.Header["Content-Type"]; !ok && r.ContentLength == 0 {
|
||||||
|
return req, close, nil
|
||||||
|
}
|
||||||
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return req, close, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
if r.ContentLength == 0 {
|
||||||
|
return req, close, nil
|
||||||
|
}
|
||||||
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return req, close, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return req, close, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var request OptPredictionParameters
|
||||||
|
if err := func() error {
|
||||||
|
request.Reset()
|
||||||
|
if err := request.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return req, close, err
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := request.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := value.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return req, close, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return request, close, nil
|
||||||
|
default:
|
||||||
|
return req, close, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
32
pkg/rest/oas_request_encoders_gen.go
Normal file
32
pkg/rest/oas_request_encoders_gen.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-faster/jx"
|
||||||
|
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func encodePerformPredictionRequest(
|
||||||
|
req OptPredictionParameters,
|
||||||
|
r *http.Request,
|
||||||
|
) error {
|
||||||
|
const contentType = "application/json"
|
||||||
|
if !req.Set {
|
||||||
|
// Keep request with empty body if value is not set.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
{
|
||||||
|
if req.Set {
|
||||||
|
req.Encode(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
encoded := e.Bytes()
|
||||||
|
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
107
pkg/rest/oas_response_decoders_gen.go
Normal file
107
pkg/rest/oas_response_decoders_gen.go
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"mime"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
"github.com/go-faster/jx"
|
||||||
|
|
||||||
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func decodePerformPredictionResponse(resp *http.Response) (res *PredictionResult, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 200:
|
||||||
|
// Code 200.
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response PredictionResult
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
55
pkg/rest/oas_response_encoders_gen.go
Normal file
55
pkg/rest/oas_response_encoders_gen.go
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
"github.com/go-faster/jx"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func encodePerformPredictionResponse(response *PredictionResult, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeErrorResponse(response *ErrorStatusCode, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
code := response.StatusCode
|
||||||
|
if code == 0 {
|
||||||
|
// Set default status code.
|
||||||
|
code = http.StatusOK
|
||||||
|
}
|
||||||
|
w.WriteHeader(code)
|
||||||
|
if st := http.StatusText(code); code >= http.StatusBadRequest {
|
||||||
|
span.SetStatus(codes.Error, st)
|
||||||
|
} else {
|
||||||
|
span.SetStatus(codes.Ok, st)
|
||||||
|
}
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
|
if code >= http.StatusInternalServerError {
|
||||||
|
return errors.Wrapf(ht.ErrInternalServerErrorResponse, "code: %d, message: %s", code, http.StatusText(code))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
178
pkg/rest/oas_router_gen.go
Normal file
178
pkg/rest/oas_router_gen.go
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ogen-go/ogen/uri"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) cutPrefix(path string) (string, bool) {
|
||||||
|
prefix := s.cfg.Prefix
|
||||||
|
if prefix == "" {
|
||||||
|
return path, true
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(path, prefix) {
|
||||||
|
// Prefix doesn't match.
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
// Cut prefix from the path.
|
||||||
|
return strings.TrimPrefix(path, prefix), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP serves http request as defined by OpenAPI v3 specification,
|
||||||
|
// calling handler that matches the path or returning not found error.
|
||||||
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
elem := r.URL.Path
|
||||||
|
elemIsEscaped := false
|
||||||
|
if rawPath := r.URL.RawPath; rawPath != "" {
|
||||||
|
if normalized, ok := uri.NormalizeEscapedPath(rawPath); ok {
|
||||||
|
elem = normalized
|
||||||
|
elemIsEscaped = strings.ContainsRune(elem, '%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elem, ok := s.cutPrefix(elem)
|
||||||
|
if !ok || len(elem) == 0 {
|
||||||
|
s.notFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static code generated router with unwrapped path search.
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case '/': // Prefix: "/api/v1/prediction"
|
||||||
|
|
||||||
|
if l := len("/api/v1/prediction"); len(elem) >= l && elem[0:l] == "/api/v1/prediction" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
s.handlePerformPredictionRequest([0]string{}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.notFound(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route is route object.
|
||||||
|
type Route struct {
|
||||||
|
name string
|
||||||
|
summary string
|
||||||
|
operationID string
|
||||||
|
pathPattern string
|
||||||
|
count int
|
||||||
|
args [0]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns ogen operation name.
|
||||||
|
//
|
||||||
|
// It is guaranteed to be unique and not empty.
|
||||||
|
func (r Route) Name() string {
|
||||||
|
return r.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary returns OpenAPI summary.
|
||||||
|
func (r Route) Summary() string {
|
||||||
|
return r.summary
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperationID returns OpenAPI operationId.
|
||||||
|
func (r Route) OperationID() string {
|
||||||
|
return r.operationID
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathPattern returns OpenAPI path.
|
||||||
|
func (r Route) PathPattern() string {
|
||||||
|
return r.pathPattern
|
||||||
|
}
|
||||||
|
|
||||||
|
// Args returns parsed arguments.
|
||||||
|
func (r Route) Args() []string {
|
||||||
|
return r.args[:r.count]
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindRoute finds Route for given method and path.
|
||||||
|
//
|
||||||
|
// Note: this method does not unescape path or handle reserved characters in path properly. Use FindPath instead.
|
||||||
|
func (s *Server) FindRoute(method, path string) (Route, bool) {
|
||||||
|
return s.FindPath(method, &url.URL{Path: path})
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindPath finds Route for given method and URL.
|
||||||
|
func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||||
|
var (
|
||||||
|
elem = u.Path
|
||||||
|
args = r.args
|
||||||
|
)
|
||||||
|
if rawPath := u.RawPath; rawPath != "" {
|
||||||
|
if normalized, ok := uri.NormalizeEscapedPath(rawPath); ok {
|
||||||
|
elem = normalized
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
for i, arg := range r.args[:r.count] {
|
||||||
|
if unescaped, err := url.PathUnescape(arg); err == nil {
|
||||||
|
r.args[i] = unescaped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
elem, ok := s.cutPrefix(elem)
|
||||||
|
if !ok {
|
||||||
|
return r, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static code generated router with unwrapped path search.
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case '/': // Prefix: "/api/v1/prediction"
|
||||||
|
|
||||||
|
if l := len("/api/v1/prediction"); len(elem) >= l && elem[0:l] == "/api/v1/prediction" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "POST":
|
||||||
|
r.name = PerformPredictionOperation
|
||||||
|
r.summary = "Perform preidction"
|
||||||
|
r.operationID = "performPrediction"
|
||||||
|
r.pathPattern = "/api/v1/prediction"
|
||||||
|
r.args = args
|
||||||
|
r.count = 0
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r, false
|
||||||
|
}
|
||||||
767
pkg/rest/oas_schemas_gen.go
Normal file
767
pkg/rest/oas_schemas_gen.go
Normal file
|
|
@ -0,0 +1,767 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *ErrorStatusCode) Error() string {
|
||||||
|
return fmt.Sprintf("code %d: %+v", s.StatusCode, s.Response)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ref: #/components/schemas/Error
|
||||||
|
type Error struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Details OptString `json:"details"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMessage returns the value of Message.
|
||||||
|
func (s *Error) GetMessage() string {
|
||||||
|
return s.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDetails returns the value of Details.
|
||||||
|
func (s *Error) GetDetails() OptString {
|
||||||
|
return s.Details
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMessage sets the value of Message.
|
||||||
|
func (s *Error) SetMessage(val string) {
|
||||||
|
s.Message = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDetails sets the value of Details.
|
||||||
|
func (s *Error) SetDetails(val OptString) {
|
||||||
|
s.Details = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorStatusCode wraps Error with StatusCode.
|
||||||
|
type ErrorStatusCode struct {
|
||||||
|
StatusCode int
|
||||||
|
Response Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStatusCode returns the value of StatusCode.
|
||||||
|
func (s *ErrorStatusCode) GetStatusCode() int {
|
||||||
|
return s.StatusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResponse returns the value of Response.
|
||||||
|
func (s *ErrorStatusCode) GetResponse() Error {
|
||||||
|
return s.Response
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatusCode sets the value of StatusCode.
|
||||||
|
func (s *ErrorStatusCode) SetStatusCode(val int) {
|
||||||
|
s.StatusCode = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetResponse sets the value of Response.
|
||||||
|
func (s *ErrorStatusCode) SetResponse(val Error) {
|
||||||
|
s.Response = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptBool returns new OptBool with value set to v.
|
||||||
|
func NewOptBool(v bool) OptBool {
|
||||||
|
return OptBool{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptBool is optional bool.
|
||||||
|
type OptBool struct {
|
||||||
|
Value bool
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptBool was set.
|
||||||
|
func (o OptBool) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptBool) Reset() {
|
||||||
|
var v bool
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptBool) SetTo(v bool) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptBool) Get() (v bool, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptBool) Or(d bool) bool {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptDateTime returns new OptDateTime with value set to v.
|
||||||
|
func NewOptDateTime(v time.Time) OptDateTime {
|
||||||
|
return OptDateTime{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptDateTime is optional time.Time.
|
||||||
|
type OptDateTime struct {
|
||||||
|
Value time.Time
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptDateTime was set.
|
||||||
|
func (o OptDateTime) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptDateTime) Reset() {
|
||||||
|
var v time.Time
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptDateTime) SetTo(v time.Time) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptDateTime) Get() (v time.Time, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptDateTime) Or(d time.Time) time.Time {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptFloat64 returns new OptFloat64 with value set to v.
|
||||||
|
func NewOptFloat64(v float64) OptFloat64 {
|
||||||
|
return OptFloat64{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptFloat64 is optional float64.
|
||||||
|
type OptFloat64 struct {
|
||||||
|
Value float64
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptFloat64 was set.
|
||||||
|
func (o OptFloat64) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptFloat64) Reset() {
|
||||||
|
var v float64
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptFloat64) SetTo(v float64) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptFloat64) Get() (v float64, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptFloat64) Or(d float64) float64 {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptPredictionParameters returns new OptPredictionParameters with value set to v.
|
||||||
|
func NewOptPredictionParameters(v PredictionParameters) OptPredictionParameters {
|
||||||
|
return OptPredictionParameters{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptPredictionParameters is optional PredictionParameters.
|
||||||
|
type OptPredictionParameters struct {
|
||||||
|
Value PredictionParameters
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptPredictionParameters was set.
|
||||||
|
func (o OptPredictionParameters) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptPredictionParameters) Reset() {
|
||||||
|
var v PredictionParameters
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptPredictionParameters) SetTo(v PredictionParameters) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptPredictionParameters) Get() (v PredictionParameters, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptPredictionParameters) Or(d PredictionParameters) PredictionParameters {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptPredictionParametersFormat returns new OptPredictionParametersFormat with value set to v.
|
||||||
|
func NewOptPredictionParametersFormat(v PredictionParametersFormat) OptPredictionParametersFormat {
|
||||||
|
return OptPredictionParametersFormat{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptPredictionParametersFormat is optional PredictionParametersFormat.
|
||||||
|
type OptPredictionParametersFormat struct {
|
||||||
|
Value PredictionParametersFormat
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptPredictionParametersFormat was set.
|
||||||
|
func (o OptPredictionParametersFormat) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptPredictionParametersFormat) Reset() {
|
||||||
|
var v PredictionParametersFormat
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptPredictionParametersFormat) SetTo(v PredictionParametersFormat) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptPredictionParametersFormat) Get() (v PredictionParametersFormat, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptPredictionParametersFormat) Or(d PredictionParametersFormat) PredictionParametersFormat {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptPredictionParametersProfile returns new OptPredictionParametersProfile with value set to v.
|
||||||
|
func NewOptPredictionParametersProfile(v PredictionParametersProfile) OptPredictionParametersProfile {
|
||||||
|
return OptPredictionParametersProfile{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptPredictionParametersProfile is optional PredictionParametersProfile.
|
||||||
|
type OptPredictionParametersProfile struct {
|
||||||
|
Value PredictionParametersProfile
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptPredictionParametersProfile was set.
|
||||||
|
func (o OptPredictionParametersProfile) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptPredictionParametersProfile) Reset() {
|
||||||
|
var v PredictionParametersProfile
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptPredictionParametersProfile) SetTo(v PredictionParametersProfile) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptPredictionParametersProfile) Get() (v PredictionParametersProfile, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptPredictionParametersProfile) Or(d PredictionParametersProfile) PredictionParametersProfile {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptString returns new OptString with value set to v.
|
||||||
|
func NewOptString(v string) OptString {
|
||||||
|
return OptString{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptString is optional string.
|
||||||
|
type OptString struct {
|
||||||
|
Value string
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptString was set.
|
||||||
|
func (o OptString) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptString) Reset() {
|
||||||
|
var v string
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptString) SetTo(v string) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptString) Get() (v string, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptString) Or(d string) string {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ref: #/components/schemas/PredictionParameters
|
||||||
|
type PredictionParameters struct {
|
||||||
|
LaunchLatitude OptFloat64 `json:"launch_latitude"`
|
||||||
|
LaunchLongitude OptFloat64 `json:"launch_longitude"`
|
||||||
|
LaunchDatetime OptDateTime `json:"launch_datetime"`
|
||||||
|
LaunchAltitude OptFloat64 `json:"launch_altitude"`
|
||||||
|
Profile OptPredictionParametersProfile `json:"profile"`
|
||||||
|
AscentRate OptFloat64 `json:"ascent_rate"`
|
||||||
|
BurstAltitude OptFloat64 `json:"burst_altitude"`
|
||||||
|
DescentRate OptFloat64 `json:"descent_rate"`
|
||||||
|
FloatAltitude OptFloat64 `json:"float_altitude"`
|
||||||
|
StopDatetime OptDateTime `json:"stop_datetime"`
|
||||||
|
// Base64 encoded ascent curve.
|
||||||
|
AscentCurve OptString `json:"ascent_curve"`
|
||||||
|
// Base64 encoded descent curve.
|
||||||
|
DescentCurve OptString `json:"descent_curve"`
|
||||||
|
Interpolate OptBool `json:"interpolate"`
|
||||||
|
Format OptPredictionParametersFormat `json:"format"`
|
||||||
|
Dataset OptDateTime `json:"dataset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLaunchLatitude returns the value of LaunchLatitude.
|
||||||
|
func (s *PredictionParameters) GetLaunchLatitude() OptFloat64 {
|
||||||
|
return s.LaunchLatitude
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLaunchLongitude returns the value of LaunchLongitude.
|
||||||
|
func (s *PredictionParameters) GetLaunchLongitude() OptFloat64 {
|
||||||
|
return s.LaunchLongitude
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLaunchDatetime returns the value of LaunchDatetime.
|
||||||
|
func (s *PredictionParameters) GetLaunchDatetime() OptDateTime {
|
||||||
|
return s.LaunchDatetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLaunchAltitude returns the value of LaunchAltitude.
|
||||||
|
func (s *PredictionParameters) GetLaunchAltitude() OptFloat64 {
|
||||||
|
return s.LaunchAltitude
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProfile returns the value of Profile.
|
||||||
|
func (s *PredictionParameters) GetProfile() OptPredictionParametersProfile {
|
||||||
|
return s.Profile
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAscentRate returns the value of AscentRate.
|
||||||
|
func (s *PredictionParameters) GetAscentRate() OptFloat64 {
|
||||||
|
return s.AscentRate
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBurstAltitude returns the value of BurstAltitude.
|
||||||
|
func (s *PredictionParameters) GetBurstAltitude() OptFloat64 {
|
||||||
|
return s.BurstAltitude
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDescentRate returns the value of DescentRate.
|
||||||
|
func (s *PredictionParameters) GetDescentRate() OptFloat64 {
|
||||||
|
return s.DescentRate
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFloatAltitude returns the value of FloatAltitude.
|
||||||
|
func (s *PredictionParameters) GetFloatAltitude() OptFloat64 {
|
||||||
|
return s.FloatAltitude
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStopDatetime returns the value of StopDatetime.
|
||||||
|
func (s *PredictionParameters) GetStopDatetime() OptDateTime {
|
||||||
|
return s.StopDatetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAscentCurve returns the value of AscentCurve.
|
||||||
|
func (s *PredictionParameters) GetAscentCurve() OptString {
|
||||||
|
return s.AscentCurve
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDescentCurve returns the value of DescentCurve.
|
||||||
|
func (s *PredictionParameters) GetDescentCurve() OptString {
|
||||||
|
return s.DescentCurve
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInterpolate returns the value of Interpolate.
|
||||||
|
func (s *PredictionParameters) GetInterpolate() OptBool {
|
||||||
|
return s.Interpolate
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFormat returns the value of Format.
|
||||||
|
func (s *PredictionParameters) GetFormat() OptPredictionParametersFormat {
|
||||||
|
return s.Format
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDataset returns the value of Dataset.
|
||||||
|
func (s *PredictionParameters) GetDataset() OptDateTime {
|
||||||
|
return s.Dataset
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLaunchLatitude sets the value of LaunchLatitude.
|
||||||
|
func (s *PredictionParameters) SetLaunchLatitude(val OptFloat64) {
|
||||||
|
s.LaunchLatitude = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLaunchLongitude sets the value of LaunchLongitude.
|
||||||
|
func (s *PredictionParameters) SetLaunchLongitude(val OptFloat64) {
|
||||||
|
s.LaunchLongitude = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLaunchDatetime sets the value of LaunchDatetime.
|
||||||
|
func (s *PredictionParameters) SetLaunchDatetime(val OptDateTime) {
|
||||||
|
s.LaunchDatetime = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLaunchAltitude sets the value of LaunchAltitude.
|
||||||
|
func (s *PredictionParameters) SetLaunchAltitude(val OptFloat64) {
|
||||||
|
s.LaunchAltitude = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProfile sets the value of Profile.
|
||||||
|
func (s *PredictionParameters) SetProfile(val OptPredictionParametersProfile) {
|
||||||
|
s.Profile = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAscentRate sets the value of AscentRate.
|
||||||
|
func (s *PredictionParameters) SetAscentRate(val OptFloat64) {
|
||||||
|
s.AscentRate = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBurstAltitude sets the value of BurstAltitude.
|
||||||
|
func (s *PredictionParameters) SetBurstAltitude(val OptFloat64) {
|
||||||
|
s.BurstAltitude = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDescentRate sets the value of DescentRate.
|
||||||
|
func (s *PredictionParameters) SetDescentRate(val OptFloat64) {
|
||||||
|
s.DescentRate = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFloatAltitude sets the value of FloatAltitude.
|
||||||
|
func (s *PredictionParameters) SetFloatAltitude(val OptFloat64) {
|
||||||
|
s.FloatAltitude = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStopDatetime sets the value of StopDatetime.
|
||||||
|
func (s *PredictionParameters) SetStopDatetime(val OptDateTime) {
|
||||||
|
s.StopDatetime = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAscentCurve sets the value of AscentCurve.
|
||||||
|
func (s *PredictionParameters) SetAscentCurve(val OptString) {
|
||||||
|
s.AscentCurve = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDescentCurve sets the value of DescentCurve.
|
||||||
|
func (s *PredictionParameters) SetDescentCurve(val OptString) {
|
||||||
|
s.DescentCurve = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInterpolate sets the value of Interpolate.
|
||||||
|
func (s *PredictionParameters) SetInterpolate(val OptBool) {
|
||||||
|
s.Interpolate = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFormat sets the value of Format.
|
||||||
|
func (s *PredictionParameters) SetFormat(val OptPredictionParametersFormat) {
|
||||||
|
s.Format = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDataset sets the value of Dataset.
|
||||||
|
func (s *PredictionParameters) SetDataset(val OptDateTime) {
|
||||||
|
s.Dataset = val
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredictionParametersFormat string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PredictionParametersFormatJSON PredictionParametersFormat = "json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all PredictionParametersFormat values.
|
||||||
|
func (PredictionParametersFormat) AllValues() []PredictionParametersFormat {
|
||||||
|
return []PredictionParametersFormat{
|
||||||
|
PredictionParametersFormatJSON,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s PredictionParametersFormat) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case PredictionParametersFormatJSON:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *PredictionParametersFormat) UnmarshalText(data []byte) error {
|
||||||
|
switch PredictionParametersFormat(data) {
|
||||||
|
case PredictionParametersFormatJSON:
|
||||||
|
*s = PredictionParametersFormatJSON
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredictionParametersProfile string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PredictionParametersProfileStandardProfile PredictionParametersProfile = "standard_profile"
|
||||||
|
PredictionParametersProfileFloatProfile PredictionParametersProfile = "float_profile"
|
||||||
|
PredictionParametersProfileReverseProfile PredictionParametersProfile = "reverse_profile"
|
||||||
|
PredictionParametersProfileCustomProfile PredictionParametersProfile = "custom_profile"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all PredictionParametersProfile values.
|
||||||
|
func (PredictionParametersProfile) AllValues() []PredictionParametersProfile {
|
||||||
|
return []PredictionParametersProfile{
|
||||||
|
PredictionParametersProfileStandardProfile,
|
||||||
|
PredictionParametersProfileFloatProfile,
|
||||||
|
PredictionParametersProfileReverseProfile,
|
||||||
|
PredictionParametersProfileCustomProfile,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s PredictionParametersProfile) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case PredictionParametersProfileStandardProfile:
|
||||||
|
return []byte(s), nil
|
||||||
|
case PredictionParametersProfileFloatProfile:
|
||||||
|
return []byte(s), nil
|
||||||
|
case PredictionParametersProfileReverseProfile:
|
||||||
|
return []byte(s), nil
|
||||||
|
case PredictionParametersProfileCustomProfile:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *PredictionParametersProfile) UnmarshalText(data []byte) error {
|
||||||
|
switch PredictionParametersProfile(data) {
|
||||||
|
case PredictionParametersProfileStandardProfile:
|
||||||
|
*s = PredictionParametersProfileStandardProfile
|
||||||
|
return nil
|
||||||
|
case PredictionParametersProfileFloatProfile:
|
||||||
|
*s = PredictionParametersProfileFloatProfile
|
||||||
|
return nil
|
||||||
|
case PredictionParametersProfileReverseProfile:
|
||||||
|
*s = PredictionParametersProfileReverseProfile
|
||||||
|
return nil
|
||||||
|
case PredictionParametersProfileCustomProfile:
|
||||||
|
*s = PredictionParametersProfileCustomProfile
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ref: #/components/schemas/PredictionResult
|
||||||
|
type PredictionResult struct {
|
||||||
|
Metadata PredictionResultMetadata `json:"metadata"`
|
||||||
|
Prediction []PredictionResultPredictionItem `json:"prediction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMetadata returns the value of Metadata.
|
||||||
|
func (s *PredictionResult) GetMetadata() PredictionResultMetadata {
|
||||||
|
return s.Metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPrediction returns the value of Prediction.
|
||||||
|
func (s *PredictionResult) GetPrediction() []PredictionResultPredictionItem {
|
||||||
|
return s.Prediction
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMetadata sets the value of Metadata.
|
||||||
|
func (s *PredictionResult) SetMetadata(val PredictionResultMetadata) {
|
||||||
|
s.Metadata = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPrediction sets the value of Prediction.
|
||||||
|
func (s *PredictionResult) SetPrediction(val []PredictionResultPredictionItem) {
|
||||||
|
s.Prediction = val
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredictionResultMetadata struct {
|
||||||
|
CompleteDatetime time.Time `json:"complete_datetime"`
|
||||||
|
StartDatetime time.Time `json:"start_datetime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCompleteDatetime returns the value of CompleteDatetime.
|
||||||
|
func (s *PredictionResultMetadata) GetCompleteDatetime() time.Time {
|
||||||
|
return s.CompleteDatetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStartDatetime returns the value of StartDatetime.
|
||||||
|
func (s *PredictionResultMetadata) GetStartDatetime() time.Time {
|
||||||
|
return s.StartDatetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCompleteDatetime sets the value of CompleteDatetime.
|
||||||
|
func (s *PredictionResultMetadata) SetCompleteDatetime(val time.Time) {
|
||||||
|
s.CompleteDatetime = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStartDatetime sets the value of StartDatetime.
|
||||||
|
func (s *PredictionResultMetadata) SetStartDatetime(val time.Time) {
|
||||||
|
s.StartDatetime = val
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredictionResultPredictionItem struct {
|
||||||
|
Stage PredictionResultPredictionItemStage `json:"stage"`
|
||||||
|
Trajectory []PredictionResultPredictionItemTrajectoryItem `json:"trajectory"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStage returns the value of Stage.
|
||||||
|
func (s *PredictionResultPredictionItem) GetStage() PredictionResultPredictionItemStage {
|
||||||
|
return s.Stage
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTrajectory returns the value of Trajectory.
|
||||||
|
func (s *PredictionResultPredictionItem) GetTrajectory() []PredictionResultPredictionItemTrajectoryItem {
|
||||||
|
return s.Trajectory
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStage sets the value of Stage.
|
||||||
|
func (s *PredictionResultPredictionItem) SetStage(val PredictionResultPredictionItemStage) {
|
||||||
|
s.Stage = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTrajectory sets the value of Trajectory.
|
||||||
|
func (s *PredictionResultPredictionItem) SetTrajectory(val []PredictionResultPredictionItemTrajectoryItem) {
|
||||||
|
s.Trajectory = val
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredictionResultPredictionItemStage string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PredictionResultPredictionItemStageAscent PredictionResultPredictionItemStage = "ascent"
|
||||||
|
PredictionResultPredictionItemStageDescent PredictionResultPredictionItemStage = "descent"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all PredictionResultPredictionItemStage values.
|
||||||
|
func (PredictionResultPredictionItemStage) AllValues() []PredictionResultPredictionItemStage {
|
||||||
|
return []PredictionResultPredictionItemStage{
|
||||||
|
PredictionResultPredictionItemStageAscent,
|
||||||
|
PredictionResultPredictionItemStageDescent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s PredictionResultPredictionItemStage) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case PredictionResultPredictionItemStageAscent:
|
||||||
|
return []byte(s), nil
|
||||||
|
case PredictionResultPredictionItemStageDescent:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *PredictionResultPredictionItemStage) UnmarshalText(data []byte) error {
|
||||||
|
switch PredictionResultPredictionItemStage(data) {
|
||||||
|
case PredictionResultPredictionItemStageAscent:
|
||||||
|
*s = PredictionResultPredictionItemStageAscent
|
||||||
|
return nil
|
||||||
|
case PredictionResultPredictionItemStageDescent:
|
||||||
|
*s = PredictionResultPredictionItemStageDescent
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PredictionResultPredictionItemTrajectoryItem struct{}
|
||||||
40
pkg/rest/oas_server_gen.go
Normal file
40
pkg/rest/oas_server_gen.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler handles operations described by OpenAPI v3 specification.
|
||||||
|
type Handler interface {
|
||||||
|
// PerformPrediction implements performPrediction operation.
|
||||||
|
//
|
||||||
|
// Perform preidction.
|
||||||
|
//
|
||||||
|
// POST /api/v1/prediction
|
||||||
|
PerformPrediction(ctx context.Context, req OptPredictionParameters, params PerformPredictionParams) (*PredictionResult, error)
|
||||||
|
// NewError creates *ErrorStatusCode from error returned by handler.
|
||||||
|
//
|
||||||
|
// Used for common default response.
|
||||||
|
NewError(ctx context.Context, err error) *ErrorStatusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server implements http server based on OpenAPI v3 specification and
|
||||||
|
// calls Handler to handle requests.
|
||||||
|
type Server struct {
|
||||||
|
h Handler
|
||||||
|
baseServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer creates new Server.
|
||||||
|
func NewServer(h Handler, opts ...ServerOption) (*Server, error) {
|
||||||
|
s, err := newServerConfig(opts...).baseServer()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Server{
|
||||||
|
h: h,
|
||||||
|
baseServer: s,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
31
pkg/rest/oas_unimplemented_gen.go
Normal file
31
pkg/rest/oas_unimplemented_gen.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnimplementedHandler is no-op Handler which returns http.ErrNotImplemented.
|
||||||
|
type UnimplementedHandler struct{}
|
||||||
|
|
||||||
|
var _ Handler = UnimplementedHandler{}
|
||||||
|
|
||||||
|
// PerformPrediction implements performPrediction operation.
|
||||||
|
//
|
||||||
|
// Perform preidction.
|
||||||
|
//
|
||||||
|
// POST /api/v1/prediction
|
||||||
|
func (UnimplementedHandler) PerformPrediction(ctx context.Context, req OptPredictionParameters, params PerformPredictionParams) (r *PredictionResult, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewError creates *ErrorStatusCode from error returned by handler.
|
||||||
|
//
|
||||||
|
// Used for common default response.
|
||||||
|
func (UnimplementedHandler) NewError(ctx context.Context, err error) (r *ErrorStatusCode) {
|
||||||
|
r = new(ErrorStatusCode)
|
||||||
|
return r
|
||||||
|
}
|
||||||
535
pkg/rest/oas_uri_gen.go
Normal file
535
pkg/rest/oas_uri_gen.go
Normal file
|
|
@ -0,0 +1,535 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
|
||||||
|
"github.com/ogen-go/ogen/conv"
|
||||||
|
"github.com/ogen-go/ogen/uri"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EncodeURI encodes PredictionParameters as URI form.
|
||||||
|
func (s *PredictionParameters) EncodeURI(e uri.Encoder) error {
|
||||||
|
if err := e.EncodeField("launch_latitude", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.LaunchLatitude.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"launch_latitude\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("launch_longitude", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.LaunchLongitude.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"launch_longitude\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("launch_datetime", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.LaunchDatetime.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.DateTimeToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"launch_datetime\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("launch_altitude", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.LaunchAltitude.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"launch_altitude\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("profile", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.Profile.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.StringToString(string(val)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"profile\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("ascent_rate", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.AscentRate.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"ascent_rate\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("burst_altitude", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.BurstAltitude.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"burst_altitude\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("descent_rate", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.DescentRate.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"descent_rate\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("float_altitude", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.FloatAltitude.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.Float64ToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"float_altitude\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("stop_datetime", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.StopDatetime.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.DateTimeToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"stop_datetime\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("ascent_curve", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.AscentCurve.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.StringToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"ascent_curve\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("descent_curve", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.DescentCurve.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.StringToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"descent_curve\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("interpolate", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.Interpolate.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.BoolToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"interpolate\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("format", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.Format.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.StringToString(string(val)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"format\"")
|
||||||
|
}
|
||||||
|
if err := e.EncodeField("dataset", func(e uri.Encoder) error {
|
||||||
|
if val, ok := s.Dataset.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.DateTimeToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode field \"dataset\"")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var uriFieldsNameOfPredictionParameters = [15]string{
|
||||||
|
0: "launch_latitude",
|
||||||
|
1: "launch_longitude",
|
||||||
|
2: "launch_datetime",
|
||||||
|
3: "launch_altitude",
|
||||||
|
4: "profile",
|
||||||
|
5: "ascent_rate",
|
||||||
|
6: "burst_altitude",
|
||||||
|
7: "descent_rate",
|
||||||
|
8: "float_altitude",
|
||||||
|
9: "stop_datetime",
|
||||||
|
10: "ascent_curve",
|
||||||
|
11: "descent_curve",
|
||||||
|
12: "interpolate",
|
||||||
|
13: "format",
|
||||||
|
14: "dataset",
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeURI decodes PredictionParameters from URI form.
|
||||||
|
func (s *PredictionParameters) DecodeURI(d uri.Decoder) error {
|
||||||
|
if s == nil {
|
||||||
|
return errors.New("invalid: unable to decode PredictionParameters to nil")
|
||||||
|
}
|
||||||
|
s.setDefaults()
|
||||||
|
|
||||||
|
if err := d.DecodeFields(func(k string, d uri.Decoder) error {
|
||||||
|
switch k {
|
||||||
|
case "launch_latitude":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotLaunchLatitudeVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotLaunchLatitudeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.LaunchLatitude.SetTo(sDotLaunchLatitudeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"launch_latitude\"")
|
||||||
|
}
|
||||||
|
case "launch_longitude":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotLaunchLongitudeVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotLaunchLongitudeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.LaunchLongitude.SetTo(sDotLaunchLongitudeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"launch_longitude\"")
|
||||||
|
}
|
||||||
|
case "launch_datetime":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotLaunchDatetimeVal time.Time
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToDateTime(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotLaunchDatetimeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.LaunchDatetime.SetTo(sDotLaunchDatetimeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"launch_datetime\"")
|
||||||
|
}
|
||||||
|
case "launch_altitude":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotLaunchAltitudeVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotLaunchAltitudeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.LaunchAltitude.SetTo(sDotLaunchAltitudeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"launch_altitude\"")
|
||||||
|
}
|
||||||
|
case "profile":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotProfileVal PredictionParametersProfile
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotProfileVal = PredictionParametersProfile(c)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Profile.SetTo(sDotProfileVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"profile\"")
|
||||||
|
}
|
||||||
|
case "ascent_rate":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotAscentRateVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotAscentRateVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.AscentRate.SetTo(sDotAscentRateVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"ascent_rate\"")
|
||||||
|
}
|
||||||
|
case "burst_altitude":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotBurstAltitudeVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotBurstAltitudeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.BurstAltitude.SetTo(sDotBurstAltitudeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"burst_altitude\"")
|
||||||
|
}
|
||||||
|
case "descent_rate":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotDescentRateVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotDescentRateVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.DescentRate.SetTo(sDotDescentRateVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"descent_rate\"")
|
||||||
|
}
|
||||||
|
case "float_altitude":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotFloatAltitudeVal float64
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToFloat64(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotFloatAltitudeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.FloatAltitude.SetTo(sDotFloatAltitudeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"float_altitude\"")
|
||||||
|
}
|
||||||
|
case "stop_datetime":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotStopDatetimeVal time.Time
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToDateTime(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotStopDatetimeVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.StopDatetime.SetTo(sDotStopDatetimeVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"stop_datetime\"")
|
||||||
|
}
|
||||||
|
case "ascent_curve":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotAscentCurveVal string
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotAscentCurveVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.AscentCurve.SetTo(sDotAscentCurveVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"ascent_curve\"")
|
||||||
|
}
|
||||||
|
case "descent_curve":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotDescentCurveVal string
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotDescentCurveVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.DescentCurve.SetTo(sDotDescentCurveVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"descent_curve\"")
|
||||||
|
}
|
||||||
|
case "interpolate":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotInterpolateVal bool
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToBool(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotInterpolateVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Interpolate.SetTo(sDotInterpolateVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"interpolate\"")
|
||||||
|
}
|
||||||
|
case "format":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotFormatVal PredictionParametersFormat
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotFormatVal = PredictionParametersFormat(c)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Format.SetTo(sDotFormatVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"format\"")
|
||||||
|
}
|
||||||
|
case "dataset":
|
||||||
|
if err := func() error {
|
||||||
|
var sDotDatasetVal time.Time
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToDateTime(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sDotDatasetVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Dataset.SetTo(sDotDatasetVal)
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return errors.Wrap(err, "decode field \"dataset\"")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "decode PredictionParameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
294
pkg/rest/oas_validators_gen.go
Normal file
294
pkg/rest/oas_validators_gen.go
Normal file
|
|
@ -0,0 +1,294 @@
|
||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package gsn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
|
|
||||||
|
"github.com/ogen-go/ogen/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *PredictionParameters) Validate() error {
|
||||||
|
if s == nil {
|
||||||
|
return validate.ErrNilPointer
|
||||||
|
}
|
||||||
|
|
||||||
|
var failures []validate.FieldError
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.LaunchLatitude.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "launch_latitude",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.LaunchLongitude.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "launch_longitude",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.LaunchAltitude.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "launch_altitude",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.Profile.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := value.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "profile",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.AscentRate.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "ascent_rate",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.BurstAltitude.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "burst_altitude",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.DescentRate.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "descent_rate",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.FloatAltitude.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := (validate.Float{}).Validate(float64(value)); err != nil {
|
||||||
|
return errors.Wrap(err, "float")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "float_altitude",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if value, ok := s.Format.Get(); ok {
|
||||||
|
if err := func() error {
|
||||||
|
if err := value.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "format",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(failures) > 0 {
|
||||||
|
return &validate.Error{Fields: failures}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s PredictionParametersFormat) Validate() error {
|
||||||
|
switch s {
|
||||||
|
case "json":
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %v", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s PredictionParametersProfile) Validate() error {
|
||||||
|
switch s {
|
||||||
|
case "standard_profile":
|
||||||
|
return nil
|
||||||
|
case "float_profile":
|
||||||
|
return nil
|
||||||
|
case "reverse_profile":
|
||||||
|
return nil
|
||||||
|
case "custom_profile":
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %v", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PredictionResult) Validate() error {
|
||||||
|
if s == nil {
|
||||||
|
return validate.ErrNilPointer
|
||||||
|
}
|
||||||
|
|
||||||
|
var failures []validate.FieldError
|
||||||
|
if err := func() error {
|
||||||
|
if s.Prediction == nil {
|
||||||
|
return errors.New("nil is invalid value")
|
||||||
|
}
|
||||||
|
var failures []validate.FieldError
|
||||||
|
for i, elem := range s.Prediction {
|
||||||
|
if err := func() error {
|
||||||
|
if err := elem.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: fmt.Sprintf("[%d]", i),
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(failures) > 0 {
|
||||||
|
return &validate.Error{Fields: failures}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "prediction",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(failures) > 0 {
|
||||||
|
return &validate.Error{Fields: failures}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PredictionResultPredictionItem) Validate() error {
|
||||||
|
if s == nil {
|
||||||
|
return validate.ErrNilPointer
|
||||||
|
}
|
||||||
|
|
||||||
|
var failures []validate.FieldError
|
||||||
|
if err := func() error {
|
||||||
|
if err := s.Stage.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "stage",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if s.Trajectory == nil {
|
||||||
|
return errors.New("nil is invalid value")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
failures = append(failures, validate.FieldError{
|
||||||
|
Name: "trajectory",
|
||||||
|
Error: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(failures) > 0 {
|
||||||
|
return &validate.Error{Fields: failures}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s PredictionResultPredictionItemStage) Validate() error {
|
||||||
|
switch s {
|
||||||
|
case "ascent":
|
||||||
|
return nil
|
||||||
|
case "descent":
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %v", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue