2023-12-29 11:30:20 +00:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-01-16 15:10:16 +00:00
|
|
|
"errors"
|
2024-11-22 11:22:08 +00:00
|
|
|
"gitea.pena/PenaSide/codeword/internal/controller/admin/admin_promocode"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/controller/admin/admin_recovery"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/controller/client/client_promocode"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/controller/client/client_recovery"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/controller/rpc_controllers"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/initialize"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/models"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/repository"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/server/grpc"
|
|
|
|
httpserver "gitea.pena/PenaSide/codeword/internal/server/http"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/services"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/utils/middleware"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/worker/purge_worker"
|
|
|
|
"gitea.pena/PenaSide/codeword/internal/worker/recovery_worker"
|
|
|
|
"gitea.pena/PenaSide/codeword/pkg/closer"
|
2025-01-02 09:42:56 +00:00
|
|
|
"gitea.pena/PenaSide/hlog"
|
|
|
|
"gitea.pena/PenaSide/trashlog/app"
|
|
|
|
"gitea.pena/PenaSide/trashlog/wrappers/zaptrashlog"
|
2024-02-25 12:02:15 +00:00
|
|
|
"github.com/twmb/franz-go/pkg/kgo"
|
2023-12-29 11:30:20 +00:00
|
|
|
"go.uber.org/zap"
|
2024-05-28 07:54:43 +00:00
|
|
|
"go.uber.org/zap/zapcore"
|
2024-01-16 15:10:16 +00:00
|
|
|
"time"
|
2023-12-29 11:30:20 +00:00
|
|
|
)
|
|
|
|
|
2024-05-28 07:54:43 +00:00
|
|
|
type Build struct {
|
|
|
|
Commit string
|
|
|
|
Version string
|
|
|
|
BuildTime int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger, build Build) error {
|
2024-01-15 20:21:16 +00:00
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
logger.Error("Recovered from a panic", zap.Any("error", r))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
logger.Info("Starting application", zap.String("AppName", cfg.AppName))
|
2023-12-29 11:30:20 +00:00
|
|
|
|
2024-01-15 08:43:55 +00:00
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
|
|
defer cancel()
|
|
|
|
|
2024-05-28 07:54:43 +00:00
|
|
|
clickHouseLogger, err := zaptrashlog.NewCore(ctx, zap.InfoLevel, cfg.TrashLogHost, build.Version, build.Commit, build.BuildTime)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
loggerForHlog := logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
|
|
|
|
return zapcore.NewTee(core, clickHouseLogger)
|
|
|
|
}))
|
|
|
|
|
2025-01-02 10:44:52 +00:00
|
|
|
loggerHlog := hlog.New(loggerForHlog).Module(initialize.ModuleLogger)
|
2024-05-28 07:54:43 +00:00
|
|
|
loggerHlog.With(models.AllFields{})
|
|
|
|
loggerHlog.Emit(app.InfoSvcStarted{})
|
|
|
|
|
2024-01-16 15:10:16 +00:00
|
|
|
shutdownGroup := closer.NewCloserGroup()
|
|
|
|
|
2024-01-11 12:07:17 +00:00
|
|
|
mdb, err := initialize.MongoDB(ctx, cfg)
|
2023-12-29 12:41:26 +00:00
|
|
|
if err != nil {
|
|
|
|
logger.Error("Failed to initialize MongoDB", zap.Error(err))
|
2024-01-15 20:21:16 +00:00
|
|
|
return err
|
2023-12-29 12:41:26 +00:00
|
|
|
}
|
|
|
|
|
2024-01-15 13:32:46 +00:00
|
|
|
if err = initialize.InitDatabaseIndexes(ctx, mdb, logger); err != nil {
|
|
|
|
logger.Error("Failed to initialize db indexes", zap.Error(err))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-02-25 12:02:15 +00:00
|
|
|
kafkaTariffClient, err := kgo.NewClient(
|
2025-01-02 10:44:52 +00:00
|
|
|
kgo.SeedBrokers(cfg.KafkaBrokers...),
|
2024-02-25 12:02:15 +00:00
|
|
|
kgo.ConsumeResetOffset(kgo.NewOffset().AtStart()),
|
2025-01-02 10:44:52 +00:00
|
|
|
kgo.DefaultProduceTopic(cfg.KafkaTopicTariff),
|
2024-02-25 12:02:15 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-03-03 10:35:38 +00:00
|
|
|
err = kafkaTariffClient.Ping(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2025-01-02 10:44:52 +00:00
|
|
|
discountRpcClient, err := initialize.DiscountGRPCClient(cfg.DiscountMicroserviceGRPC)
|
2024-02-25 12:02:15 +00:00
|
|
|
if err != nil {
|
|
|
|
logger.Error("failed to connect to discount service", zap.Error(err))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
brokers := initialize.NewBrokers(initialize.BrokersDeps{
|
|
|
|
Logger: logger,
|
|
|
|
TariffClient: kafkaTariffClient,
|
2025-01-02 10:44:52 +00:00
|
|
|
Topic: cfg.KafkaTopicTariff,
|
2024-02-25 12:02:15 +00:00
|
|
|
})
|
2024-01-17 13:51:42 +00:00
|
|
|
|
2024-01-11 12:07:17 +00:00
|
|
|
rdb, err := initialize.Redis(ctx, cfg)
|
2024-03-03 07:34:19 +00:00
|
|
|
if err != nil {
|
|
|
|
logger.Error("failed to connect to redis db", zap.Error(err))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-11 12:07:17 +00:00
|
|
|
encrypt := initialize.Encrypt(cfg)
|
2024-01-11 16:29:53 +00:00
|
|
|
|
2024-01-11 18:20:33 +00:00
|
|
|
promoCodeRepo := repository.NewPromoCodeRepository(mdb.Collection("promoCodes"))
|
2024-01-27 12:51:32 +00:00
|
|
|
statsRepo := repository.NewStatsRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("promoStats")})
|
2023-12-31 12:22:03 +00:00
|
|
|
codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")})
|
|
|
|
userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")})
|
2024-01-11 16:29:53 +00:00
|
|
|
|
2024-01-05 11:37:06 +00:00
|
|
|
recoveryEmailSender := initialize.RecoveryEmailSender(cfg, logger)
|
|
|
|
authClient := initialize.AuthClient(cfg, logger)
|
2023-12-29 18:02:50 +00:00
|
|
|
|
|
|
|
recoveryService := services.NewRecoveryService(services.Deps{
|
2023-12-31 12:22:03 +00:00
|
|
|
Logger: logger,
|
|
|
|
CodewordRepository: codewordRepo,
|
|
|
|
UserRepository: userRepo,
|
2024-01-04 11:27:50 +00:00
|
|
|
Encrypt: encrypt,
|
2024-01-04 14:57:30 +00:00
|
|
|
AuthClient: authClient,
|
2023-12-29 18:02:50 +00:00
|
|
|
})
|
|
|
|
|
2024-01-11 16:29:53 +00:00
|
|
|
promoService := services.NewPromoCodeService(services.PromoDeps{
|
2024-02-25 12:02:15 +00:00
|
|
|
Logger: logger,
|
|
|
|
PromoCodeRepo: promoCodeRepo,
|
|
|
|
StatsRepo: statsRepo,
|
|
|
|
Kafka: brokers.TariffProducer,
|
|
|
|
DiscountClient: discountRpcClient,
|
2024-01-11 16:29:53 +00:00
|
|
|
})
|
|
|
|
|
2024-05-28 11:05:31 +00:00
|
|
|
jwtUtil := middleware.NewJWT(&cfg)
|
2024-03-03 10:13:13 +00:00
|
|
|
|
2024-07-12 08:26:15 +00:00
|
|
|
clientRecoveryController := client_recovery.NewRecoveryController(client_recovery.Deps{
|
2024-05-28 11:05:31 +00:00
|
|
|
Logger: logger,
|
|
|
|
Service: recoveryService,
|
|
|
|
DefaultURL: cfg.DefaultRedirectionURL,
|
2025-01-02 10:44:52 +00:00
|
|
|
RecoveryURL: cfg.MailRecoveryURL,
|
2024-05-28 11:05:31 +00:00
|
|
|
})
|
2024-07-12 08:26:15 +00:00
|
|
|
clientPromoCodeController := client_promocode.NewPromoCodeController(client_promocode.Deps{Logger: logger, PromoCodeService: promoService})
|
|
|
|
|
|
|
|
adminRecoveryController := admin_recovery.NewRecoveryController(admin_recovery.Deps{
|
2025-01-02 10:44:52 +00:00
|
|
|
Logger: logger,
|
|
|
|
Service: recoveryService,
|
2024-07-12 08:26:15 +00:00
|
|
|
})
|
|
|
|
adminPromoCodeController := admin_promocode.NewPromoCodeController(admin_promocode.Deps{Logger: logger, PromoCodeService: promoService})
|
2024-04-25 12:09:28 +00:00
|
|
|
controllerRpc := rpc_controllers.InitRpcControllers(promoService)
|
|
|
|
|
|
|
|
grpcServer, err := grpc.NewGRPC(logger)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error("error init rpc server", zap.Error(err))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
grpcServer.Register(controllerRpc)
|
2023-12-29 12:41:26 +00:00
|
|
|
|
2024-01-03 13:50:11 +00:00
|
|
|
recoveryWC := recovery_worker.NewRecoveryWC(recovery_worker.Deps{
|
|
|
|
Logger: logger,
|
|
|
|
Redis: rdb,
|
|
|
|
EmailSender: recoveryEmailSender,
|
2024-01-03 15:45:41 +00:00
|
|
|
Mongo: mdb.Collection("codeword"),
|
2024-01-03 13:50:11 +00:00
|
|
|
})
|
2024-01-01 14:13:54 +00:00
|
|
|
|
2024-01-16 15:10:16 +00:00
|
|
|
purgeWC := purge_worker.NewPurgeWC(purge_worker.Deps{
|
2024-01-05 11:37:06 +00:00
|
|
|
Logger: logger,
|
|
|
|
Mongo: mdb.Collection("codeword"),
|
|
|
|
})
|
|
|
|
|
2024-01-01 14:13:54 +00:00
|
|
|
go recoveryWC.Start(ctx)
|
2024-01-05 11:37:06 +00:00
|
|
|
go purgeWC.Start(ctx)
|
2024-01-01 14:13:54 +00:00
|
|
|
|
2024-07-12 08:26:15 +00:00
|
|
|
clientServer := httpserver.NewServer(httpserver.ServerConfig{
|
|
|
|
Logger: logger,
|
|
|
|
Controllers: []httpserver.Controller{clientRecoveryController, clientPromoCodeController},
|
|
|
|
Hlogger: loggerHlog,
|
|
|
|
JWT: jwtUtil,
|
|
|
|
})
|
|
|
|
|
|
|
|
adminServer := httpserver.NewServer(httpserver.ServerConfig{
|
2024-02-25 12:00:05 +00:00
|
|
|
Logger: logger,
|
2024-07-12 08:26:15 +00:00
|
|
|
Controllers: []httpserver.Controller{adminRecoveryController, adminPromoCodeController},
|
2024-05-28 07:54:43 +00:00
|
|
|
Hlogger: loggerHlog,
|
2024-05-28 11:05:31 +00:00
|
|
|
JWT: jwtUtil,
|
2023-12-29 11:30:20 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
go func() {
|
2025-01-02 10:44:52 +00:00
|
|
|
if err := clientServer.Start(cfg.ClientHttpURL); err != nil {
|
2024-07-12 08:26:15 +00:00
|
|
|
logger.Error("Client server startup error", zap.Error(err))
|
|
|
|
cancel()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
2025-01-02 10:44:52 +00:00
|
|
|
if err := adminServer.Start(cfg.AdminHttpURL); err != nil {
|
2024-07-12 08:26:15 +00:00
|
|
|
logger.Error("Admin server startup error", zap.Error(err))
|
2024-01-16 15:10:16 +00:00
|
|
|
cancel()
|
2023-12-29 11:30:20 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2025-01-02 10:44:52 +00:00
|
|
|
go grpcServer.Run(cfg.GrpcURL)
|
2024-04-25 12:09:28 +00:00
|
|
|
|
2024-07-12 08:26:15 +00:00
|
|
|
clientServer.ListRoutes()
|
|
|
|
adminServer.ListRoutes()
|
2024-02-25 12:00:05 +00:00
|
|
|
|
2024-07-12 08:26:15 +00:00
|
|
|
shutdownGroup.Add(closer.CloserFunc(clientServer.Shutdown))
|
|
|
|
shutdownGroup.Add(closer.CloserFunc(adminServer.Shutdown))
|
2024-04-25 12:09:28 +00:00
|
|
|
shutdownGroup.Add(closer.CloserFunc(grpcServer.Stop))
|
2024-01-16 15:10:16 +00:00
|
|
|
shutdownGroup.Add(closer.CloserFunc(mdb.Client().Disconnect))
|
|
|
|
shutdownGroup.Add(closer.CloserFunc(recoveryWC.Stop))
|
|
|
|
shutdownGroup.Add(closer.CloserFunc(purgeWC.Stop))
|
2023-12-29 18:02:50 +00:00
|
|
|
|
2024-01-16 15:10:16 +00:00
|
|
|
<-ctx.Done()
|
2023-12-29 18:02:50 +00:00
|
|
|
|
2024-01-16 15:10:16 +00:00
|
|
|
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))
|
|
|
|
}
|
2023-12-29 18:02:50 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-16 15:10:16 +00:00
|
|
|
logger.Info("Application has stopped")
|
2023-12-29 11:30:20 +00:00
|
|
|
return nil
|
|
|
|
}
|