123 lines
3.5 KiB
Go
123 lines
3.5 KiB
Go
package app
|
||
|
||
import (
|
||
"codeword/internal/adapters/client"
|
||
controller "codeword/internal/controller/recovery"
|
||
"codeword/internal/initialize"
|
||
"codeword/internal/repository"
|
||
httpserver "codeword/internal/server/http"
|
||
"codeword/internal/services"
|
||
"codeword/internal/utils/encrypt"
|
||
"codeword/internal/worker/recovery_worker"
|
||
"context"
|
||
"github.com/gofiber/fiber/v2"
|
||
"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)
|
||
|
||
encryptService := encrypt.New(&encrypt.EncryptDeps{
|
||
PublicKey: cfg.PublicCurveKey,
|
||
PrivateKey: cfg.PrivateCurveKey,
|
||
SignSecret: cfg.SignSecret,
|
||
})
|
||
|
||
codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")})
|
||
userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")})
|
||
|
||
recoveryEmailSender := client.NewRecoveryEmailSender(client.RecoveryEmailSenderDeps{
|
||
SmtpApiUrl: cfg.SmtpApiUrl,
|
||
SmtpHost: cfg.SmtpHost,
|
||
SmtpPort: cfg.SmtpPort,
|
||
SmtpSender: cfg.SmtpSender,
|
||
Username: cfg.SmtpUsername,
|
||
Password: cfg.SmtpPassword,
|
||
ApiKey: cfg.SmtpApiKey,
|
||
FiberClient: &fiber.Client{},
|
||
Logger: logger,
|
||
})
|
||
|
||
recoveryService := services.NewRecoveryService(services.Deps{
|
||
Logger: logger,
|
||
CodewordRepository: codewordRepo,
|
||
UserRepository: userRepo,
|
||
EncryptService: encryptService,
|
||
})
|
||
|
||
recoveryController := controller.NewRecoveryController(logger, recoveryService)
|
||
|
||
recoveryWC := recovery_worker.NewRecoveryWC(recovery_worker.Deps{
|
||
Logger: logger,
|
||
Redis: rdb,
|
||
EmailSender: recoveryEmailSender,
|
||
})
|
||
|
||
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
|
||
}
|