package main import ( "context" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "github.com/CubeCraft-Creations/Extrudex/backend/internal/config" "github.com/CubeCraft-Creations/Extrudex/backend/internal/db" "github.com/CubeCraft-Creations/Extrudex/backend/internal/router" "github.com/CubeCraft-Creations/Extrudex/backend/internal/sse" ) func main() { // Setup structured logging slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: slog.LevelInfo, }))) // Load configuration cfg, err := config.Load() if err != nil { slog.Error("failed to load config", "error", err) os.Exit(1) } slog.Info("config loaded", "port", cfg.Port, "cors_origin", cfg.CorsOrigin) // Connect to database dbPool, err := db.NewPool(cfg.DatabaseURL) if err != nil { slog.Error("failed to connect to database", "error", err) os.Exit(1) } defer db.ClosePool(dbPool) slog.Info("database connected") // Create SSE broadcaster and start it sseBC := sse.NewBroadcaster(128) sseBC.Start() defer sseBC.Stop() slog.Info("sse broadcaster started") // Create router r := router.New(cfg, dbPool, sseBC) // Create HTTP server // WriteTimeout is 0 for SSE support — the Chi middleware.Timeout(60s) // handles request-level timeouts on non-SSE routes. server := &http.Server{ Addr: ":" + cfg.Port, Handler: r, ReadTimeout: 15 * time.Second, WriteTimeout: 0, // disabled for SSE long-lived connections IdleTimeout: 60 * time.Second, } // Start server in goroutine go func() { slog.Info("server starting", "addr", server.Addr) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error("server error", "error", err) os.Exit(1) } }() // Wait for shutdown signal quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit slog.Info("server shutting down") // Graceful shutdown ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { slog.Error("server shutdown error", "error", err) } db.ClosePool(dbPool) slog.Info("server stopped") }