package main import ( "context" "flag" "log/slog" "os" "os/signal" "syscall" "time" "yobble-gateway-go/internal/config" "yobble-gateway-go/internal/logger" "yobble-gateway-go/internal/server" "yobble-gateway-go/pkg/geoip" ) func main() { var configPath string flag.StringVar(&configPath, "config", "configs/config.yml", "config file path") flag.Parse() if configPath == "" { configPath = os.Getenv("CONFIG_PATH") } op := "main.main" log := logger.NewLoggerWithOp(op) cfg, err := config.Load(log, configPath) if err != nil { log.Error("failed to load configuration", slog.String("path", configPath), slog.Any("error", err)) os.Exit(1) } logger.InitLogger(&cfg.Logger) log = logger.NewLoggerWithOp(op) log.Info("configuration loaded successfully") log.Debug("ROUTE CFG: ", slog.Any("routes", cfg.RouteConfig)) // Инициализируем сервис GeoIP geoipService, err := geoip.NewGeoIPService(&cfg.Gateway) if err != nil { log.Error("failed to initialize GeoIP service", slog.Any("error", err)) os.Exit(1) } defer geoipService.Close() // Создаем экземпляр сервера srv := server.NewServer(cfg, geoipService) // Запускаем сервер в отдельной горутине done := make(chan struct{}) errChan := srv.Start(&cfg.TLS) // Настраиваем перехват системных сигналов для graceful shutdown sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) go func() { select { case err := <-errChan: if err != nil { log.Error("server error", slog.Any("error", err)) } case sig := <-sigChan: log.Info("received signal", slog.String("signal", sig.String())) // Создаем контекст с таймаутом для graceful shutdown shutdownCtx, cancel := context.WithTimeout(context.Background(), 35*time.Second) // TODO: Make configurable defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Error("server graceful shutdown failed", slog.Any("error", err)) os.Exit(1) } } close(done) }() <-done log.Info("application stopped") }