package main import ( "context" "log/slog" "net/http" "os" "os/signal" "syscall" "time" apihttp "platform-projects-core/internal/api/http" "platform-projects-core/internal/config" "platform-projects-core/internal/infrastructure/auth" "platform-projects-core/internal/infrastructure/postgres" "platform-projects-core/internal/observability" ) func main() { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() cfg, err := config.Load() if err != nil { slog.Error("config error", "error", err) os.Exit(1) } logger := observability.NewLogger(cfg.Environment) logger.Info("starting service", "service", cfg.ServiceName) pool, err := postgres.NewPool(ctx, cfg.Database) if err != nil { logger.Error("database connection failed", "error", err) os.Exit(1) } defer pool.Close() jwtValidator, err := auth.NewValidator(ctx, cfg.Auth) if err != nil { logger.Error("jwt validator init failed", "error", err) os.Exit(1) } router := apihttp.NewRouter(apihttp.RouterDependencies{ Logger: logger, DB: pool, JWTValidator: jwtValidator, Config: cfg, }) srv := &http.Server{ Addr: cfg.HTTP.Address, Handler: router, ReadHeaderTimeout: 5 * time.Second, } go func() { <-ctx.Done() shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { logger.Error("http shutdown error", "error", err) } }() logger.Info("http server listening", "addr", cfg.HTTP.Address) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Error("http server failed", "error", err) os.Exit(1) } logger.Info("service stopped") }