core/app/app.go

260 lines
7.8 KiB
Go
Raw Normal View History

2024-02-19 17:48:04 +00:00
package app
import (
"context"
"errors"
"fmt"
"github.com/go-redis/redis/v8"
2024-02-19 17:48:04 +00:00
"github.com/gofiber/fiber/v2"
"github.com/skeris/appInit"
"github.com/themakers/hlog"
"go.uber.org/zap"
2024-06-25 14:41:26 +00:00
"go.uber.org/zap/zapcore"
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
2024-03-25 09:47:18 +00:00
"penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege"
2024-02-19 17:48:04 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/healthchecks"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/middleware"
2024-03-25 09:47:18 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
2024-06-12 13:27:42 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/core/brokers"
"penahub.gitlab.yandexcloud.net/backend/quiz/core/clients/auth"
2024-06-25 14:37:26 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/core/clients/telegram"
2024-06-12 13:27:42 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/core/initialize"
"penahub.gitlab.yandexcloud.net/backend/quiz/core/models"
"penahub.gitlab.yandexcloud.net/backend/quiz/core/server"
"penahub.gitlab.yandexcloud.net/backend/quiz/core/service"
"penahub.gitlab.yandexcloud.net/backend/quiz/core/tools"
"penahub.gitlab.yandexcloud.net/backend/quiz/core/workers"
"penahub.gitlab.yandexcloud.net/external/trashlog/wrappers/zaptrashlog"
"time"
2024-02-19 17:48:04 +00:00
)
type App struct {
logger *zap.Logger
err chan error
}
func (a App) GetLogger() *zap.Logger {
return a.logger
}
func (a App) GetErr() chan error {
return a.err
}
var (
errInvalidOptions = errors.New("invalid options")
)
var zapOptions = []zap.Option{
zap.AddCaller(),
zap.AddCallerSkip(2),
zap.AddStacktrace(zap.ErrorLevel),
}
var _ appInit.CommonApp = (*App)(nil)
type Options struct {
LoggerProdMode bool `env:"IS_PROD_LOG" default:"false"`
IsProd bool `env:"IS_PROD" default:"false"`
NumberPort string `env:"PORT" default:"1488"`
CrtFile string `env:"CRT" default:"server.crt"`
KeyFile string `env:"KEY" default:"server.key"`
2024-03-26 17:48:49 +00:00
PostgresCredentials string `env:"PG_CRED" default:"host=localhost port=35432 user=squiz password=Redalert2 dbname=squiz sslmode=disable"`
HubAdminUrl string `env:"HUB_ADMIN_URL" default:"http://localhost:8001/"`
2024-03-25 09:47:18 +00:00
ServiceName string `env:"SERVICE_NAME" default:"squiz"`
2024-03-26 17:48:49 +00:00
AuthServiceURL string `env:"AUTH_URL" default:"http://localhost:8000/"`
2024-04-03 15:32:05 +00:00
GrpcHost string `env:"GRPC_HOST" default:"localhost"`
GrpcPort string `env:"GRPC_PORT" default:"9000"`
KafkaBrokers string `env:"KAFKA_BROKERS" default:"localhost:9092"`
KafkaTopic string `env:"KAFKA_TOPIC" default:"test-topic"`
KafkaGroup string `env:"KAFKA_GROUP" default:"mailnotifier"`
2024-06-02 08:19:22 +00:00
TrashLogHost string `env:"TRASH_LOG_HOST" default:"localhost:7113"`
ModuleLogger string `env:"MODULE_LOGGER" default:"core-local"`
ClickHouseCred string `env:"CLICK_HOUSE_CRED" default:"tcp://10.8.0.15:9000/default?sslmode=disable"`
RedisHost string `env:"REDIS_HOST" default:"localhost:6379"`
RedisPassword string `env:"REDIS_PASSWORD" default:"admin"`
RedisDB uint64 `env:"REDIS_DB" default:"2"`
S3Prefix string `env:"S3_PREFIX"`
2024-02-19 17:48:04 +00:00
}
func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.CommonApp, error) {
var (
err, workerErr error
zapLogger *zap.Logger
errChan = make(chan error)
options Options
ok bool
)
if options, ok = opts.(Options); !ok {
return App{}, errInvalidOptions
}
if options.LoggerProdMode {
zapLogger, err = zap.NewProduction(zapOptions...)
if err != nil {
return nil, err
}
} else {
zapLogger, err = zap.NewDevelopment(zapOptions...)
if err != nil {
return nil, err
}
}
2024-06-15 19:36:34 +00:00
zapLogger = zapLogger.With(
zap.String("SvcCommit", ver.Commit),
zap.String("SvcVersion", ver.Release),
zap.String("SvcBuildTime", ver.BuildTime),
)
2024-06-02 08:19:22 +00:00
2024-06-25 14:41:26 +00:00
clickHouseLogger, err := zaptrashlog.NewCore(ctx, zap.InfoLevel, options.TrashLogHost, ver.Release, ver.Commit, time.Now().Unix())
if err != nil {
panic(err)
}
loggerForHlog := zapLogger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return zapcore.NewTee(core, clickHouseLogger)
}))
2024-02-19 17:48:04 +00:00
2024-06-25 14:41:26 +00:00
loggerHlog := hlog.New(loggerForHlog).Module(options.ModuleLogger)
2024-06-02 08:19:22 +00:00
loggerHlog.With(models.AllFields{})
loggerHlog.Emit(InfoSvcStarted{})
2024-02-19 17:48:04 +00:00
2024-03-25 09:47:18 +00:00
authClient := auth.NewAuthClient(options.AuthServiceURL)
2024-02-19 17:48:04 +00:00
2024-04-16 08:56:47 +00:00
pgdal, err := dal.New(ctx, options.PostgresCredentials, nil)
2024-02-19 17:48:04 +00:00
if err != nil {
fmt.Println("NEW", err)
return nil, err
}
chDal, err := dal.NewClickHouseDAL(ctx, options.ClickHouseCred)
if err != nil {
fmt.Println("failed init clickhouse", err)
return nil, err
}
kafkaClient, err := initialize.KafkaInit(ctx, initialize.KafkaDeps{
KafkaGroup: options.KafkaGroup,
KafkaBrokers: options.KafkaBrokers,
KafkaTopic: options.KafkaTopic,
})
2024-04-26 18:54:18 +00:00
if err != nil {
return nil, err
}
producer := brokers.NewProducer(brokers.ProducerDeps{
KafkaClient: kafkaClient,
Logger: zapLogger,
})
redisClient := redis.NewClient(&redis.Options{
Addr: options.RedisHost,
Password: options.RedisPassword,
DB: int(options.RedisDB),
})
err = redisClient.Ping(ctx).Err()
if err != nil {
panic(fmt.Sprintf("error ping to redis db %v", err))
}
2024-03-25 09:47:18 +00:00
clientData := privilege.Client{
URL: options.HubAdminUrl,
ServiceName: options.ServiceName,
Privileges: model.Privileges,
}
fiberClient := &fiber.Client{}
privilegeController := privilege.NewPrivilege(clientData, fiberClient)
go tools.PublishPrivilege(privilegeController, 10, 5*time.Minute)
2024-03-25 09:47:18 +00:00
tgClient, err := telegram.NewTelegramClient(ctx, pgdal)
2024-06-25 14:37:26 +00:00
if err != nil {
2024-06-30 18:02:23 +00:00
panic(fmt.Sprintf("failed init tg clietns: %v", err))
2024-06-25 14:37:26 +00:00
}
tgWC := workers.NewTgListenerWC(workers.Deps{
BotID: int64(6712573453), // todo убрать
Redis: redisClient,
Dal: pgdal,
TgClient: tgClient,
})
go tgWC.Start(ctx)
2024-04-03 15:32:05 +00:00
// todo подумать над реализацией всего а то пока мне кажется что немного каша получается такой предикт что через некоторое время
// сложно будет разобраться что есть где
grpcControllers := initialize.InitRpcControllers(pgdal)
grpc, err := server.NewGRPC(zapLogger)
if err != nil {
fmt.Println("error:", err)
panic("err init grpc server")
}
grpc.Register(grpcControllers)
go grpc.Run(server.DepsGrpcRun{
Host: options.GrpcHost,
Port: options.GrpcPort,
})
2024-02-19 17:48:04 +00:00
app := fiber.New()
app.Use(middleware.JWTAuth())
app.Use(log_mw.ContextLogger(loggerHlog))
2024-02-19 17:48:04 +00:00
app.Get("/liveness", healthchecks.Liveness)
app.Get("/readiness", healthchecks.Readiness(&workerErr)) //todo parametrized readiness. should discuss ready reason
2024-03-22 12:42:52 +00:00
svc := service.New(service.Deps{
2024-06-30 18:02:23 +00:00
Dal: pgdal,
AuthClient: authClient,
Producer: producer,
ServiceName: options.ServiceName,
ChDAL: chDal,
TelegramClient: tgClient,
RedisClient: redisClient,
2024-09-17 11:21:26 +00:00
S3Prefix: options.S3Prefix,
2024-03-22 12:42:52 +00:00
})
2024-02-19 17:48:04 +00:00
svc.Register(app)
2024-06-02 08:19:22 +00:00
loggerHlog.Emit(InfoSvcReady{})
2024-02-19 17:48:04 +00:00
go func() {
defer func() {
if pgdal != nil {
pgdal.Close()
}
if chDal != nil {
2024-08-06 13:56:51 +00:00
if derr := chDal.Close(ctx); derr != nil {
fmt.Printf("error closing clickhouse: %v", derr)
}
}
2024-04-03 15:32:05 +00:00
err := grpc.Stop(ctx)
err = app.Shutdown()
2024-06-02 08:19:22 +00:00
loggerHlog.Emit(InfoSvcShutdown{Signal: err.Error()})
2024-02-19 17:48:04 +00:00
}()
if options.IsProd {
if err := app.ListenTLS(fmt.Sprintf(":%s", options.NumberPort), options.CrtFile, options.KeyFile); err != nil {
2024-06-02 08:19:22 +00:00
loggerHlog.Emit(ErrorCanNotServe{
2024-02-19 17:48:04 +00:00
Err: err,
})
errChan <- err
}
} else {
if err := app.Listen(fmt.Sprintf(":%s", options.NumberPort)); err != nil {
2024-06-02 08:19:22 +00:00
loggerHlog.Emit(ErrorCanNotServe{
2024-02-19 17:48:04 +00:00
Err: err,
})
errChan <- err
}
}
errChan <- nil
}()
// todo implement helper func for service app type. such as server preparing, logger preparing, healthchecks and etc.
return &App{
logger: zapLogger,
err: errChan,
}, err
}