package main import ( "context" "flag" "fmt" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "edp.buildth.ing/DevFW-CICD/forgejo-runner-optimiser/internal/receiver" ) const ( defaultAddr = ":8080" defaultDBPath = "metrics.db" ) func main() { addr := flag.String("addr", defaultAddr, "HTTP listen address") dbPath := flag.String("db", defaultDBPath, "SQLite database path") readToken := flag.String("read-token", os.Getenv("RECEIVER_READ_TOKEN"), "Pre-shared token for read endpoints (or set RECEIVER_READ_TOKEN)") hmacKey := flag.String("hmac-key", os.Getenv("RECEIVER_HMAC_KEY"), "Secret key for push token generation/validation (or set RECEIVER_HMAC_KEY)") tokenTTL := flag.Duration("token-ttl", 2*time.Hour, "Time-to-live for push tokens (default 2h)") flag.Parse() logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ Level: slog.LevelInfo, })) store, err := receiver.NewStore(*dbPath) if err != nil { logger.Error("failed to open database", slog.String("error", err.Error())) os.Exit(1) } defer func() { _ = store.Close() }() handler := receiver.NewHandler(store, logger, *readToken, *hmacKey, *tokenTTL) mux := http.NewServeMux() handler.RegisterRoutes(mux) server := &http.Server{ Addr: *addr, Handler: mux, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, } ctx, cancel := context.WithCancel(context.Background()) defer cancel() sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-sigChan logger.Info("received signal, shutting down", slog.String("signal", sig.String())) cancel() shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) defer shutdownCancel() _ = server.Shutdown(shutdownCtx) }() logger.Info("starting metrics receiver", slog.String("addr", *addr), slog.String("db", *dbPath), ) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } <-ctx.Done() logger.Info("receiver stopped gracefully") }