database/client.go

346 lines
8.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package mysql ...
//
// Description : mysql客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-03-01 9:20 下午
package mysql
import (
"fmt"
"path/filepath"
"strings"
"sync"
"git.zhangdeman.cn/zhangdeman/util"
"git.zhangdeman.cn/zhangdeman/logger/wrapper"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"git.zhangdeman.cn/zhangdeman/logger"
gormLogger "gorm.io/gorm/logger"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var (
// Client mysql客户端
Client *client
)
func init() {
Client = &client{
lock: &sync.RWMutex{},
clientTable: make(map[string]*DBClient),
}
}
type client struct {
lock *sync.RWMutex
clientTable map[string]*DBClient
}
// AddWithConfigFile 使用文件生成新的客户端文件名去掉后缀作为flag
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:19 2022/6/5
func (c *client) AddWithConfigFile(cfgFile string) error {
return nil
}
// BatchAddWithConfigDir 自动读取目录下配置文件, 生成客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:19 2022/6/5
func (c *client) BatchAddWithConfigDir(cfgDir string) error {
return nil
}
// getMysqlCfgFileList 获取mysql配置文件列表
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:39 2022/6/9
func (c *client) getMysqlCfgFileList(cfgDir string) ([]cfgFile, error) {
filepathNames, _ := filepath.Glob(filepath.Join(cfgDir, "*"))
cfgFileList := make([]cfgFile, 0)
for i := range filepathNames {
fileArr := strings.Split(filepathNames[i], ".")
if len(fileArr) < 2 {
// 获取不到类型
continue
}
fileType := strings.ToLower(fileArr[len(fileArr)-1])
switch fileType {
case FileTypeYaml:
fallthrough
case FileTypeYml:
cfgFileList = append(cfgFileList, cfgFile{
Path: filepathNames[i],
Type: FileTypeYaml,
})
util.File.ReadYmlConfig()
case FileTypeJson:
cfgFileList = append(cfgFileList, cfgFile{
Path: filepathNames[i],
Type: FileTypeJson,
})
default:
// 不是JSON , 也不是YML, 跳过
continue
}
}
return cfgFileList, nil
}
// GetDBClient 获取db client
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:32 2022/6/5
func (c *client) GetDBClient(ctx *gin.Context, dbFlag string) (*DBClient, error) {
c.lock.RLock()
defer c.lock.RUnlock()
var (
exist bool
dbClient *DBClient
)
if dbClient, exist = c.clientTable[dbFlag]; !exist {
return nil, fmt.Errorf("%s 标识的数据库实例不存在! ", dbFlag)
}
return dbClient, nil
}
// GetMasterClient 获取主库客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:36 2022/6/5
func (c *client) GetMasterClient(ctx *gin.Context, dbFlag string) (*gorm.DB, error) {
var (
err error
dbClient *DBClient
)
if dbClient, err = c.GetDBClient(ctx, dbFlag); nil != err {
return nil, err
}
session := dbClient.master.Session(&gorm.Session{})
session.Logger = dbClient.getLogger(ctx, session, dbFlag+"-master")
return session, nil
}
// GetSlaveClient 获取从库客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:37 2022/6/5
func (c *client) GetSlaveClient(ctx *gin.Context, dbFlag string) (*gorm.DB, error) {
var (
err error
dbClient *DBClient
)
if dbClient, err = c.GetDBClient(ctx, dbFlag); nil != err {
return nil, err
}
session := dbClient.slave.Session(&gorm.Session{})
session.Logger = dbClient.getLogger(ctx, session, dbFlag+"-slave")
return session, nil
}
// getLogInstance 获取日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:23 2022/6/5
func (c *client) getLogInstance(logConf *LogConfig, loggerInstance *zap.Logger) (*zap.Logger, error) {
if nil != loggerInstance {
return loggerInstance, nil
}
if nil == logConf {
return nil, nil
}
logConfList := []logger.SetLoggerOptionFunc{logger.WithEncoder(logConf.Encoder), logger.WithCallerSkip(logConf.Skip), logger.WithCaller()}
if logConf.ConsoleOutput {
logConfList = append(logConfList, logger.WithConsoleOutput())
}
var (
err error
)
if loggerInstance, err = logger.NewLogger(logConf.Level, logConf.SplitConfig, logConfList...); nil != err {
return nil, err
}
return loggerInstance, nil
}
// getGormClient 获取GORM client方法
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:24 2022/6/6
func (c *client) getGormClient() (*gorm.DB, error) {
return nil, nil
}
// BatchNewDBClient 批量设置数据库实例, 读取指定目录下的yaml文件, 文件名作为标识, 内容是数据库具体配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:43 2022/6/5
func BatchNewDBClient(dbConfigDir string) {
}
// NewDBClient ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:09 PM 2021/12/24
func NewDBClient(masterConf *DBConfig, slaveConf *DBConfig, logConf *LogConfig, loggerInstance *zap.Logger, extraRequestFieldList []string) (*DBClient, error) {
client := &DBClient{
extraFieldList: extraRequestFieldList,
}
var err error
// 日志初始化失败
if client.loggerInstance, err = getLogInstance(logConf, loggerInstance); nil != err {
return nil, err
}
if client.master, err = GetDatabaseClient(masterConf, nil); nil != err {
return nil, err
}
if client.slave, err = GetDatabaseClient(slaveConf, nil); nil != err {
return nil, err
}
return client, nil
}
// DBClient 包装日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:09 PM 2021/12/24
type DBClient struct {
dbFlag string // 数据库标识
loggerInstance *zap.Logger // 日志实例
master *gorm.DB // 主库
slave *gorm.DB // 从库
extraFieldList []string // 提取的字段
}
// SetFlag 设置数据库标识
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:18 2022/6/5
func (dc *DBClient) SetFlag(dbFlag string) {
dc.dbFlag = dbFlag
}
// GetMaster 获取主库连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:28 PM 2021/12/24
func (dc *DBClient) GetMaster(ctx *gin.Context) *gorm.DB {
session := dc.master.Session(&gorm.Session{})
session.Logger = dc.getLogger(ctx, session, "slave")
return session
}
// GetSlave 获取从库链接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:29 PM 2021/12/24
func (dc *DBClient) GetSlave(ctx *gin.Context) *gorm.DB {
session := dc.slave.Session(&gorm.Session{})
session.Logger = dc.getLogger(ctx, session, "slave")
return session
}
// getLogger 获取日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:45 PM 2021/12/24
func (dc *DBClient) getLogger(ctx *gin.Context, dbClient *gorm.DB, node string) gormLogger.Interface {
return wrapper.NewGormLoggerWithInstance(ctx, dbClient, dc.loggerInstance, node, dc.extraFieldList)
}
// getLogInstance 获取日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:20 PM 2021/12/24
func getLogInstance(logConf *LogConfig, loggerInstance *zap.Logger) (*zap.Logger, error) {
if nil != loggerInstance {
return loggerInstance, nil
}
if nil == logConf {
return nil, nil
}
logConfList := []logger.SetLoggerOptionFunc{logger.WithEncoder(logConf.Encoder), logger.WithCallerSkip(logConf.Skip), logger.WithCaller()}
if logConf.ConsoleOutput {
logConfList = append(logConfList, logger.WithConsoleOutput())
}
var (
err error
)
if loggerInstance, err = logger.NewLogger(logConf.Level, logConf.SplitConfig, logConfList...); nil != err {
return nil, err
}
return loggerInstance, nil
}
// GetDatabaseClient 获取日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:49 下午 2021/3/1
func GetDatabaseClient(conf *DBConfig, logConf *LogConfig) (*gorm.DB, error) {
var (
instance *gorm.DB
err error
loggerInstance *zap.Logger
)
if instance, err = gorm.Open(mysql.Open(buildConnectionDSN(conf)), &gorm.Config{}); nil != err {
return nil, err
}
if nil != logConf {
if loggerInstance, err = getLogInstance(logConf, nil); nil != err {
return nil, err
}
instance.Logger = wrapper.NewGormLoggerWithInstance(nil, instance, loggerInstance, "", nil)
}
return instance, nil
}
// buildConnectionDSN 构建建立连接的DSN
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 9:34 下午 2021/3/1
func buildConnectionDSN(conf *DBConfig) string {
return fmt.Sprintf(
"%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
conf.Username,
conf.Password,
conf.Host,
conf.Port,
conf.Database,
conf.Charset,
)
}