package app import ( controller "codeword/internal/controller/recovery" "codeword/internal/initialize" "codeword/internal/repository" httpserver "codeword/internal/server/http" "codeword/internal/services" "codeword/internal/worker/recovery_worker" "context" "go.mongodb.org/mongo-driver/mongo" "go.uber.org/zap" "time" ) func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error { logger.Info("Запуск приложения", zap.String("AppName", cfg.AppName)) mdb, err := initialize.InitializeMongoDB(ctx, cfg) if err != nil { logger.Error("Failed to initialize MongoDB", zap.Error(err)) return err } rdb, err := initialize.InitializeRedis(ctx, cfg) encrypt := initialize.InitializeEncrypt(cfg) codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")}) userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")}) recoveryEmailSender := initialize.InitializeRecoveryEmailSender(cfg, logger) authClient := initialize.InitializeAuthClient(cfg, logger) recoveryService := services.NewRecoveryService(services.Deps{ Logger: logger, CodewordRepository: codewordRepo, UserRepository: userRepo, Encrypt: encrypt, AuthClient: authClient, }) recoveryController := controller.NewRecoveryController(logger, recoveryService, cfg.DefaultRedirectionURL) recoveryWC := recovery_worker.NewRecoveryWC(recovery_worker.Deps{ Logger: logger, Redis: rdb, EmailSender: recoveryEmailSender, Mongo: mdb.Collection("codeword"), }) go recoveryWC.Start(ctx) server := httpserver.NewServer(httpserver.ServerConfig{ Logger: logger, RecoveryController: recoveryController, }) go func() { if err := server.Start(cfg.HTTPHost + ":" + cfg.HTTPPort); err != nil { logger.Error("Ошибка запуска сервера", zap.Error(err)) } }() <-ctx.Done() if err := shutdownApp(server, mdb, logger); err != nil { return err } logger.Info("Приложение остановлено") return nil } // TODO возможно стоит вынести в отдельные файлы или отказаться от разделения на отдельные методы func shutdownApp(server *httpserver.Server, mdb *mongo.Database, logger *zap.Logger) error { if err := shutdownHTTPServer(server, logger); err != nil { return err } if err := shutdownMongoDB(mdb, logger); err != nil { return err } return nil } func shutdownHTTPServer(server *httpserver.Server, logger *zap.Logger) error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { logger.Error("Ошибка при остановке HTTP-сервера", zap.Error(err)) return err } return nil } func shutdownMongoDB(mdb *mongo.Database, logger *zap.Logger) error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := mdb.Client().Disconnect(ctx); err != nil { logger.Error("Ошибка при закрытии соединения с MongoDB", zap.Error(err)) return err } return nil }