package main import ( "context" "errors" "net/http" "os" "os/signal" "syscall" "time" "warpbox.dev/backend/libs/config" "warpbox.dev/backend/libs/httpserver" "warpbox.dev/backend/libs/logging" ) func main() { cfg, err := config.Load() if err != nil { os.Stderr.WriteString("failed to load config: " + err.Error() + "\n") os.Exit(1) } logger, closeLogs, err := logging.New(cfg.DataDir) if err != nil { os.Stderr.WriteString("failed to create logger: " + err.Error() + "\n") os.Exit(1) } defer closeLogs() server, err := httpserver.New(cfg, logger) if err != nil { logger.Error("failed to create server", "source", "startup", "severity", "error", "error", err.Error()) os.Exit(1) } errs := make(chan error, 1) go func() { logger.Info("warpbox server starting", "source", "startup", "severity", "dev", "addr", cfg.Addr, "env", cfg.Environment) errs <- server.ListenAndServe() }() shutdown := make(chan os.Signal, 1) signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM) select { case err := <-errs: if err != nil && !errors.Is(err, http.ErrServerClosed) { logger.Error("server stopped unexpectedly", "source", "startup", "severity", "error", "error", err.Error()) os.Exit(1) } case sig := <-shutdown: logger.Info("shutdown signal received", "source", "startup", "severity", "dev", "signal", sig.String()) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { logger.Error("graceful shutdown failed", "source", "startup", "severity", "error", "error", err.Error()) os.Exit(1) } logger.Info("server stopped", "source", "startup", "severity", "dev") } }