All checks were successful
ci/woodpecker/push/build-image Pipeline was successful
113 lines
3.5 KiB
Go
113 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/httpapi"
|
|
adapterpg "gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/postgres"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/application/alerts"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/application/conditions"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/application/forecasts"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/application/observations"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/application/units"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/platform/config"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/platform/constants"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/platform/datasource"
|
|
dspostgres "gitea.maximumdirect.net/ejr/weatherapi/internal/platform/datasource/postgres"
|
|
)
|
|
|
|
func main() {
|
|
cfgPath := flag.String("config", "config.yml", "path to YAML config")
|
|
addr := flag.String("addr", constants.DefaultHTTPAddr, "HTTP listen address")
|
|
dbName := flag.String("db-name", "", "optional configured database name to use")
|
|
flag.Parse()
|
|
|
|
cfg, err := config.Load(*cfgPath)
|
|
if err != nil {
|
|
log.Fatalf("load config: %v", err)
|
|
}
|
|
|
|
dbCfg, err := chooseDatabase(cfg, *dbName)
|
|
if err != nil {
|
|
log.Fatalf("select database: %v", err)
|
|
}
|
|
|
|
registry := datasource.NewRegistry()
|
|
if err := registry.Register(dspostgres.Factory{}); err != nil {
|
|
log.Fatalf("register datasource factories: %v", err)
|
|
}
|
|
|
|
ds, err := registry.Open(context.Background(), dbCfg)
|
|
if err != nil {
|
|
log.Fatalf("open datasource %q: %v", dbCfg.Name, err)
|
|
}
|
|
defer ds.Close()
|
|
|
|
pgDataSource, ok := ds.(*dspostgres.DataSource)
|
|
if !ok {
|
|
log.Fatalf("unsupported datasource type %T for driver %q", ds, dbCfg.Driver)
|
|
}
|
|
|
|
unitRegistry, err := newUnitRegistry()
|
|
if err != nil {
|
|
log.Fatalf("configure units: %v", err)
|
|
}
|
|
|
|
obsRepo := adapterpg.NewObservationRepository(pgDataSource.Pool())
|
|
fcRepo := adapterpg.NewForecastRepository(pgDataSource.Pool())
|
|
alertRepo := adapterpg.NewAlertRepository(pgDataSource.Pool())
|
|
|
|
obsSvc := observations.NewService(obsRepo, unitRegistry)
|
|
conditionsSvc := conditions.NewService(obsRepo, unitRegistry, constants.ObservationWindow)
|
|
fcSvc := forecasts.NewService(fcRepo, unitRegistry, constants.ForecastQueryLimit)
|
|
alertsSvc := alerts.NewService(alertRepo)
|
|
|
|
server := httpapi.NewServer(obsSvc, conditionsSvc, fcSvc, alertsSvc)
|
|
|
|
httpServer := &http.Server{
|
|
Addr: *addr,
|
|
Handler: server.Handler(),
|
|
}
|
|
|
|
log.Printf("weatherapi listening on %s (db=%s driver=%s units=per-request)", *addr, dbCfg.Name, dbCfg.Driver)
|
|
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
log.Fatalf("http server: %v", err)
|
|
}
|
|
}
|
|
|
|
func chooseDatabase(cfg *config.Config, name string) (config.DatabaseConfig, error) {
|
|
if cfg == nil {
|
|
return config.DatabaseConfig{}, fmt.Errorf("config is nil")
|
|
}
|
|
if name == "" {
|
|
return cfg.Databases[0], nil
|
|
}
|
|
|
|
db, ok := cfg.FindDatabase(name)
|
|
if !ok {
|
|
return config.DatabaseConfig{}, fmt.Errorf("database %q not found in config", name)
|
|
}
|
|
return db, nil
|
|
}
|
|
|
|
func newUnitRegistry() (*units.Registry, error) {
|
|
registry := units.NewRegistry()
|
|
if err := registry.Register(units.StaticFactory{
|
|
UnitSystem: constants.UnitSystemUS,
|
|
Converter: units.USConverter{},
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := registry.Register(units.StaticFactory{
|
|
UnitSystem: constants.UnitSystemMetric,
|
|
Converter: units.MetricConverter{},
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
return registry, nil
|
|
}
|