package app import ( "context" "database/sql" "fmt" "log" "os" "os/signal" "syscall" "time" _ "github.com/jackc/pgx/v5/stdlib" "github.com/joho/godotenv" ) func Run() error { _ = godotenv.Load() cfg, err := loadConfig() if err != nil { return fmt.Errorf("config error: %w", err) } db, err := sql.Open("pgx", cfg.DatabaseURL) if err != nil { return fmt.Errorf("database open error: %w", err) } defer db.Close() if err := db.Ping(); err != nil { return fmt.Errorf("database ping error: %w", err) } app := &App{cfg: cfg, db: db} if err := app.migrate(context.Background()); err != nil { return fmt.Errorf("migration error: %w", err) } handler := app.routes() servers, cleanup, err := startServers(cfg, handler) if err != nil { return fmt.Errorf("server start error: %w", err) } defer cleanup() log.Printf("server started: tcp=%q unix=%q dev_mode=%t", cfg.ListenAddr, cfg.UnixSocketPath, cfg.DevMode) sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) <-sigCh ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() for _, s := range servers { if err := s.Shutdown(ctx); err != nil { log.Printf("shutdown error: %v", err) } } log.Printf("shutdown complete") return nil }