// main.go с graceful shutdown package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "go.uber.org/zap" "gorm.io/driver/postgres" "gorm.io/gorm" "api_bb/internal/config" "api_bb/internal/models" "api_bb/internal/routes" "api_bb/pkg/logger" ) func main() { // Загрузка конфигурации cfg := config.Load() // Инициализация логгера if err := logger.Init( os.Getenv("LOG_LEVEL"), os.Getenv("ENVIRONMENT"), ); err != nil { log.Printf("Failed to initialize logger: %v", err) os.Exit(1) } defer logger.Sync() zapLogger := logger.Get() // Логируем начало работы logger.LogApplicationStart(os.Getenv("REST_API_VERSION"), os.Getenv("ENVIRONMENT"), "") // Подключение к базе данных db, err := gorm.Open(postgres.Open(cfg.DatabaseURL), &gorm.Config{}) if err != nil { zapLogger.Fatal("failed to connect to database", zap.Error(err)) } // Автомиграция if err := db.AutoMigrate(&models.User{}); err != nil { zapLogger.Fatal("database migration failed", zap.Error(err)) } // Настройка роутера router := routes.SetupRouter(db, cfg) // Настройка HTTP сервера server := &http.Server{ Addr: ":" + cfg.Port, Handler: router, } // Канал для graceful shutdown done := make(chan bool, 1) quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt, syscall.SIGTERM) // Запуск сервера в горутине go func() { zapLogger.Info("starting HTTP server", zap.String("port", cfg.Port)) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { zapLogger.Fatal("failed to start server", zap.Error(err)) } }() // Ожидание сигнала shutdown <-quit zapLogger.Info("shutdown signal received") // Graceful shutdown ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() server.SetKeepAlivesEnabled(false) if err := server.Shutdown(ctx); err != nil { zapLogger.Fatal("could not gracefully shutdown the server", zap.Error(err)) } logger.LogApplicationShutdown("graceful shutdown") close(done) }