package main // @title Watch Party Backend API // @version 1.0 // @description Backend API for watch-party app. // @BasePath / // @schemes http https // @host localhost:8082 import ( "context" "log" "net/http" "time" _ "watch-party-backend/docs" "watch-party-backend/internal/auth" "watch-party-backend/internal/config" "watch-party-backend/internal/db" httpapi "watch-party-backend/internal/http" "watch-party-backend/internal/repo" "watch-party-backend/internal/service" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" "github.com/gin-gonic/gin" ) func main() { // 1) config cfg := config.Load() gin.SetMode(cfg.GinMode) // 2) DB pool ctx := context.Background() pool, err := db.NewPool(ctx, cfg.DB.DSN(), cfg.DB.MaxConns) if err != nil { log.Fatalf("db connect failed: %v", err) } defer pool.Close() // 3) wiring episodeRepo := repo.NewEpisodeRepo(pool) episodeSvc := service.NewEpisodeService(episodeRepo) var verifier auth.TokenVerifier if cfg.Auth.Enabled { v, err := auth.NewFirebaseAuth(ctx, cfg.Firebase) if err != nil { log.Fatalf("firebase auth init failed: %v", err) } verifier = v log.Printf("auth enabled (project: %s)", cfg.Firebase.ProjectID) } else { log.Printf("auth disabled (AUTH_ENABLED=false)") } router := httpapi.NewRouter(episodeSvc, verifier, cfg.Auth.Enabled) router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) // 4) HTTP server with timeouts s := &http.Server{ Addr: cfg.Addr, Handler: router, ReadTimeout: 10 * time.Second, ReadHeaderTimeout: 5 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second, } log.Printf("listening on %s (dsn: %s)", cfg.Addr, config.RedactDSN(cfg.DB.DSN())) if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("server error: %v", err) } }