package app import ( "context" "errors" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/backend/quiz/shutterstock/internal/client" "penahub.gitlab.yandexcloud.net/backend/quiz/shutterstock/internal/controller" "penahub.gitlab.yandexcloud.net/backend/quiz/shutterstock/internal/initialize" "penahub.gitlab.yandexcloud.net/backend/quiz/shutterstock/internal/server/http" "penahub.gitlab.yandexcloud.net/backend/quiz/shutterstock/pkg/closer" "time" ) func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error { defer func() { if r := recover(); r != nil { logger.Error("Recovered from a panic", zap.Any("error", r)) } }() ctx, cancel := context.WithCancel(ctx) defer cancel() shutdownGroup := closer.NewCloserGroup() shutterStockClient := client.NewShutterStockClient(client.Deps{ ShutterStockApiToken: cfg.ShutterStockApiToken, ShutterStockUrl: cfg.ShutterStockUrl, Logger: logger, }) shutterStockController := controller.NewShutterStockController(shutterStockClient) srv := http.NewServer(http.ServerConfig{ Logger: logger, Controllers: []http.Controller{shutterStockController}, }) go func() { if err := srv.Start(cfg.HTTPHost + ":" + cfg.HTTPPort); err != nil { logger.Error("Server startup error", zap.Error(err)) cancel() } }() srv.ListRoutes() shutdownGroup.Add(closer.CloserFunc(srv.Shutdown)) <-ctx.Done() timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), 10*time.Second) defer timeoutCancel() if err := shutdownGroup.Call(timeoutCtx); err != nil { if errors.Is(err, context.DeadlineExceeded) { logger.Error("Shutdown timed out", zap.Error(err)) } else { logger.Error("Failed to shutdown services gracefully", zap.Error(err)) } return err } logger.Info("Application has stopped") return nil }