package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "datarush/internal/gw/config" "datarush/internal/gw/grpc_client" "datarush/internal/gw/handler" "datarush/internal/gw/middleware" "datarush/internal/gw/router" "datarush/internal/gw/storage" ) func main() { cfg, err := config.Load() if err != nil { log.Fatalf("Failed to load config: %v", err) } ctx := context.Background() clientFactory := grpc_client.NewClientFactory() defer clientFactory.Close() authClient, err := grpc_client.NewAuthClient(ctx, cfg.GRPC.AuthServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create auth client: %v", err) } userClient, err := grpc_client.NewUserClient(ctx, cfg.GRPC.UserServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create user client: %v", err) } competitionClient, err := grpc_client.NewCompetitionClient(ctx, cfg.GRPC.CompetitionServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create competition client: %v", err) } taskClient, err := grpc_client.NewTaskClient(ctx, cfg.GRPC.TaskServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create task client: %v", err) } submissionClient, err := grpc_client.NewSubmissionClient(ctx, cfg.GRPC.SubmissionServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create submission client: %v", err) } resultsClient, err := grpc_client.NewResultsClient(ctx, cfg.GRPC.ResultsServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create results client: %v", err) } reviewClient, err := grpc_client.NewReviewClient(ctx, cfg.GRPC.ReviewServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create review client: %v", err) } achievementsClient, err := grpc_client.NewAchievementsClient(ctx, cfg.GRPC.AchievementsServiceAddr, clientFactory) if err != nil { log.Fatalf("Failed to create achievements client: %v", err) } s3Storage, err := storage.NewS3Storage(storage.S3Config{ AccessKeyID: cfg.S3.AccessKeyID, SecretAccessKey: cfg.S3.SecretAccessKey, Region: cfg.S3.Region, Bucket: cfg.S3.Bucket, Endpoint: cfg.S3.Endpoint, }) if err != nil { log.Fatalf("Failed to create S3 storage: %v", err) } authMiddleware := middleware.NewAuthMiddleware(authClient) authHandler := handler.NewAuthHandler(authClient, userClient) competitionHandler := handler.NewCompetitionHandler(competitionClient, userClient) taskHandler := handler.NewTaskHandler(taskClient) submissionHandler := handler.NewSubmissionHandler(submissionClient, s3Storage) resultsHandler := handler.NewResultsHandler(resultsClient) reviewHandler := handler.NewReviewHandler(reviewClient) achievementsHandler := handler.NewAchievementsHandler(achievementsClient) pingHandler := handler.NewPingHandler() rt := router.NewRouter( authHandler, competitionHandler, taskHandler, submissionHandler, resultsHandler, reviewHandler, achievementsHandler, pingHandler, authMiddleware, ) httpHandler := rt.Setup() addr := fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port) server := &http.Server{ Addr: addr, Handler: httpHandler, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } go func() { log.Printf("Starting API Gateway on %s", addr) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Failed to start server: %v", err) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down server...") shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := server.Shutdown(shutdownCtx); err != nil { log.Fatalf("Server forced to shutdown: %v", err) } log.Println("Server exited") }