package main import ( "context" "fmt" "net/http" "os" "os/signal" "syscall" "time" "github.com/prabhupadasays/spsays-bff/internal/config" "github.com/prabhupadasays/spsays-bff/internal/server" "go.uber.org/zap" ) func main() { // Load config cfg, err := config.Load() if err != nil { fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err) os.Exit(1) } // Initialize logger var logger *zap.Logger if cfg.Env == "production" { logger, _ = zap.NewProduction() } else { logger, _ = zap.NewDevelopment() } defer logger.Sync() sugar := logger.Sugar() // Create server srv := server.New(cfg, logger) // Start HTTP server httpServer := &http.Server{ Addr: fmt.Sprintf(":%d", cfg.Port), Handler: srv.Router(), ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } // Graceful shutdown go func() { sugar.Infof("🚀 Server starting on port %d (%s)", cfg.Port, cfg.Env) if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { sugar.Fatalf("server error: %v", err) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit sugar.Info("🛑 Shutting down server...") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := httpServer.Shutdown(ctx); err != nil { sugar.Fatalf("forced shutdown: %v", err) } // Close connections srv.Close() sugar.Info("✅ Server stopped gracefully") }