|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
Ihttp "cls/pkg/http"
|
|
|
|
"cls/pkg/logger"
|
|
|
|
"cls/pkg/sms"
|
|
|
|
"cls/pkg/util/security"
|
|
|
|
"cls/pkg/xorm_engine"
|
|
|
|
"cls/ui"
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
auth_middleware "cls/internal/infrastructure/middleware/auth"
|
|
|
|
"github.com/ClickHouse/clickhouse-go/v2"
|
|
|
|
"github.com/cenkalti/backoff/v4"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
|
|
"net"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
middleware "cls/pkg/web/middleware"
|
|
|
|
|
|
|
|
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"go.uber.org/fx"
|
|
|
|
"xorm.io/xorm"
|
|
|
|
"xorm.io/xorm/names"
|
|
|
|
)
|
|
|
|
|
|
|
|
func NewGinEngine(lc fx.Lifecycle, auth *auth_middleware.AuthMiddleware, appConfig *AppConfig) *gin.Engine {
|
|
|
|
if strings.ToLower(appConfig.ServerConfig.Mode) == "prod" {
|
|
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
}
|
|
|
|
handler := gin.New()
|
|
|
|
handler.Use(gin.Recovery())
|
|
|
|
handler.Use(auth.Handle())
|
|
|
|
handler.Use(middleware.ServeRoot("/", "dist", &ui.RESOURCE))
|
|
|
|
handler.NoRoute(func(context *gin.Context) {
|
|
|
|
if context.Request.RequestURI != "/" {
|
|
|
|
context.Redirect(http.StatusTemporaryRedirect, "/")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
srv := &http.Server{Addr: fmt.Sprintf(":%d", appConfig.ServerConfig.Port), Handler: handler}
|
|
|
|
lc.Append(fx.Hook{
|
|
|
|
OnStart: func(ctx context.Context) error {
|
|
|
|
ln, err := net.Listen("tcp", srv.Addr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Infof("Web server starting on port %v", srv.Addr)
|
|
|
|
log.Info("Press Ctrl+C to stop")
|
|
|
|
go func() {
|
|
|
|
if err0 := srv.Serve(ln); err0 != nil {
|
|
|
|
log.Error(err0)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
OnStop: func(ctx context.Context) error {
|
|
|
|
return srv.Shutdown(ctx)
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return handler
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewXormEngine(appConfig *AppConfig, l logger.New) *xorm_engine.Engine {
|
|
|
|
dbConfig := appConfig.MysqlConfig
|
|
|
|
url := fmt.Sprintf("%s:%s@(%s)/%s", dbConfig.Username, dbConfig.Password, dbConfig.Address, dbConfig.Database)
|
|
|
|
engine, err := xorm.NewEngineWithParams("mysql", url, dbConfig.Params)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
fmt.Println("done")
|
|
|
|
engine.SetTableMapper(names.NewPrefixMapper(names.GonicMapper{}, "lc_"))
|
|
|
|
engine.SetColumnMapper(names.GonicMapper{})
|
|
|
|
engine.SetLogger(logger.NewXormLogger(l("xorm")))
|
|
|
|
if dbConfig.ShowSql {
|
|
|
|
engine.ShowSQL(true)
|
|
|
|
}
|
|
|
|
if err = backoff.Retry(engine.Ping, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
urlCls := fmt.Sprintf("%s:%s@(%s)/%s", dbConfig.Username, dbConfig.Password, dbConfig.Address, dbConfig.DatabaseCls)
|
|
|
|
engineCls, err := xorm.NewEngineWithParams("mysql", urlCls, dbConfig.Params)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if err = backoff.Retry(engineCls.Ping, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return xorm_engine.NewEngine(engine, engineCls)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewClickhouseConn(appConfig *AppConfig) driver.Conn {
|
|
|
|
dbConfig := appConfig.ClickhouseConfig
|
|
|
|
conn, err := clickhouse.Open(&clickhouse.Options{
|
|
|
|
Addr: dbConfig.Address,
|
|
|
|
Auth: clickhouse.Auth{
|
|
|
|
Database: dbConfig.Database,
|
|
|
|
Username: dbConfig.Username,
|
|
|
|
Password: dbConfig.Password,
|
|
|
|
},
|
|
|
|
Settings: clickhouse.Settings{
|
|
|
|
"max_execution_time": 60,
|
|
|
|
},
|
|
|
|
Compression: &clickhouse.Compression{
|
|
|
|
Method: clickhouse.CompressionLZ4,
|
|
|
|
},
|
|
|
|
DialTimeout: time.Duration(10) * time.Second,
|
|
|
|
MaxOpenConns: 5,
|
|
|
|
MaxIdleConns: 5,
|
|
|
|
ConnMaxLifetime: time.Duration(10) * time.Minute,
|
|
|
|
ConnOpenStrategy: clickhouse.ConnOpenInOrder,
|
|
|
|
BlockBufferSize: 10,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if err = backoff.Retry(func() error {
|
|
|
|
return conn.Ping(context.Background())
|
|
|
|
}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if v, err := conn.ServerVersion(); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
} else {
|
|
|
|
log.Info(v)
|
|
|
|
}
|
|
|
|
return conn
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRedisClient(appConfig *AppConfig) redis.Cmdable {
|
|
|
|
dbConfig := appConfig.RedisConfig
|
|
|
|
var rdbCli redis.Cmdable
|
|
|
|
switch dbConfig.Mode {
|
|
|
|
case "sentinel":
|
|
|
|
rdbCli = redis.NewFailoverClient(&redis.FailoverOptions{
|
|
|
|
MasterName: dbConfig.MasterName,
|
|
|
|
SentinelAddrs: dbConfig.SentinelAddrs,
|
|
|
|
SentinelUsername: dbConfig.SentinelUsername,
|
|
|
|
SentinelPassword: dbConfig.SentinelPassword,
|
|
|
|
Username: dbConfig.Username,
|
|
|
|
Password: dbConfig.Password,
|
|
|
|
DB: 0,
|
|
|
|
})
|
|
|
|
case "cluster":
|
|
|
|
rdbCli = redis.NewClusterClient(&redis.ClusterOptions{
|
|
|
|
Addrs: dbConfig.Addrs,
|
|
|
|
Username: dbConfig.Username,
|
|
|
|
Password: dbConfig.Password,
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
rdbCli = redis.NewClient(&redis.Options{
|
|
|
|
Addr: dbConfig.Addr,
|
|
|
|
Username: dbConfig.Username,
|
|
|
|
Password: dbConfig.Password,
|
|
|
|
DB: dbConfig.DB,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if err := backoff.Retry(func() error {
|
|
|
|
return rdbCli.Ping(context.Background()).Err()
|
|
|
|
}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return rdbCli
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewLoggerFactory(config *AppConfig) logger.New {
|
|
|
|
return func(name string) logger.Logger {
|
|
|
|
var options []logger.Option
|
|
|
|
if v, ok := config.LogConfig.Loggers[strings.ToLower(name)]; ok {
|
|
|
|
options = append(options, logger.Level(logger.LogLevel(v)))
|
|
|
|
}
|
|
|
|
return logger.NewLogger(name, options...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPasswordEncoder() security.PasswordEncoder {
|
|
|
|
return &security.BCryptPasswordEncoder{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSmsService() sms.IsmsService {
|
|
|
|
return sms.NewSmsService()
|
|
|
|
}
|
|
|
|
func NewInternalClient() *Ihttp.Client {
|
|
|
|
return Ihttp.NewClient()
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewJWTAuthMiddleware(appConfig *AppConfig, log logger.New, redis redis.Cmdable) *auth_middleware.AuthMiddleware {
|
|
|
|
return auth_middleware.NewAuthMiddleware(appConfig.JwtConfig.Secret, nil, redis, log)
|
|
|
|
}
|