86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
// main.go wires configuration, dependencies, and HTTP runtime startup.
|
|
// Layer: cmd/weatherapi executable composition root.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
|
|
feedapp "gitea.maximumdirect.net/ejr/feedapi/app"
|
|
"gitea.maximumdirect.net/ejr/feedapi/config"
|
|
"gitea.maximumdirect.net/ejr/feedapi/db"
|
|
httpapi "gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/inbound/httpapi"
|
|
wfpq "gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/outbound/postgres"
|
|
"gitea.maximumdirect.net/ejr/weatherapi/internal/app"
|
|
|
|
_ "github.com/lib/pq"
|
|
)
|
|
|
|
func main() {
|
|
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
|
|
|
|
cfgPath := flag.String("config", envOrDefault("WEATHERAPI_CONFIG", "config.yml"), "Path to config YAML")
|
|
flag.Parse()
|
|
|
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
defer cancel()
|
|
|
|
if err := run(ctx, *cfgPath); err != nil {
|
|
log.Fatalf("weatherapi failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func run(ctx context.Context, cfgPath string) error {
|
|
cfg, err := config.Load(cfgPath)
|
|
if err != nil {
|
|
return fmt.Errorf("load config: %w", err)
|
|
}
|
|
if len(cfg.Databases) == 0 {
|
|
return fmt.Errorf("config.databases requires at least one entry")
|
|
}
|
|
|
|
reg, err := db.OpenAll(cfg.Databases)
|
|
if err != nil {
|
|
return fmt.Errorf("open databases: %w", err)
|
|
}
|
|
defer func() {
|
|
if cerr := reg.Close(); cerr != nil {
|
|
log.Printf("database close error: %v", cerr)
|
|
}
|
|
}()
|
|
|
|
primaryName := cfg.Databases[0].Name
|
|
primary, err := reg.Get(primaryName)
|
|
if err != nil {
|
|
return fmt.Errorf("select primary database %q: %w", primaryName, err)
|
|
}
|
|
|
|
repo := wfpq.NewRepository(primary)
|
|
svc := app.NewService(repo)
|
|
defs := httpapi.Definitions(svc)
|
|
|
|
a, err := feedapp.New(cfg,
|
|
feedapp.WithDBRegistry(reg),
|
|
feedapp.WithEndpoints(defs...),
|
|
)
|
|
if err != nil {
|
|
return fmt.Errorf("build app: %w", err)
|
|
}
|
|
|
|
return a.Start(ctx)
|
|
}
|
|
|
|
func envOrDefault(key, fallback string) string {
|
|
v := strings.TrimSpace(os.Getenv(key))
|
|
if v == "" {
|
|
return fallback
|
|
}
|
|
return v
|
|
}
|