From 0098405793c802e8d5351b3bb3c8ff696fe20e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 21 Aug 2024 16:01:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=20wrapper=5Fdb=5Fclient,=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=A1=A8=E7=BB=93=E6=9E=84=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E5=AE=9A=E6=97=B6=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- abstract/wrapper_db_client.go | 6 +- define/table.go | 18 ++++++ system.go | 9 +-- wrapper_db_client.go | 107 +++++++++++++++++++++++++++++++--- 4 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 define/table.go diff --git a/abstract/wrapper_db_client.go b/abstract/wrapper_db_client.go index 118719e..104646f 100644 --- a/abstract/wrapper_db_client.go +++ b/abstract/wrapper_db_client.go @@ -21,11 +21,15 @@ import ( // Date : 18:00 2024/8/20 type IWrapperDatabaseClient interface { // Init 初始化客户端连接 - Init(databaseConfig *define.Database) error + Init(databaseConfig *define.Database, cacheTableStructureConfig *define.CacheTableStructureConfig) error // GetMaster 获取master连接 GetMaster(ctx context.Context) *gorm.DB // GetSlave 获取slave连接 GetSlave(ctx context.Context) *gorm.DB // GetDatabaseClient 获取数据库连接 GetDatabaseClient(conf *define.Driver, logInstance *zap.Logger) (*gorm.DB, error) + // CacheDataTableStructureConfig 缓存数据表结构的配置 + CacheDataTableStructureConfig() *define.CacheTableStructureConfig + // GetTableFieldList 获取指定表数据字段列表 + GetTableFieldList(tableName string) ([]*define.ColumnInfo, error) } diff --git a/define/table.go b/define/table.go new file mode 100644 index 0000000..91edc05 --- /dev/null +++ b/define/table.go @@ -0,0 +1,18 @@ +// Package define ... +// +// Description : define ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-08-21 14:56 +package define + +// CacheTableStructureConfig 缓存表结构的配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 14:56 2024/8/21 +type CacheTableStructureConfig struct { + Enable bool `json:"enable"` // 是否启用表结构缓存 + SyncTimeInterval int `json:"sync_time_interval"` // 开启的情况向, 多久同步一次表结构, 默认值 3600, 单位 : s +} diff --git a/system.go b/system.go index ae9cecd..670cf71 100644 --- a/system.go +++ b/system.go @@ -12,6 +12,7 @@ import ( "gorm.io/driver/mysql" + "git.zhangdeman.cn/zhangdeman/database/define" "gorm.io/gorm" ) @@ -99,10 +100,10 @@ func (sd *SystemDao) GetCreateTableSQL(dbInstance *gorm.DB, table string) (strin // Author : go_developer@163.com<白茶清欢> // // Date : 22:37 2023/8/16 -func (sd *SystemDao) GetTableDesc(dbInstance *gorm.DB, database string, tableName string) ([]*DescTableItem, error) { +func (sd *SystemDao) GetTableDesc(dbInstance *gorm.DB, database string, tableName string) ([]*define.DescTableItem, error) { var ( err error - result []*DescTableItem + result []*define.DescTableItem ) if err = dbInstance.Raw("DESC `" + tableName + "`").Scan(&result).Error; nil != err { @@ -125,9 +126,9 @@ func (sd *SystemDao) GetTableDesc(dbInstance *gorm.DB, database string, tableNam // Author : go_developer@163.com<白茶清欢> // // Date : 23:10 2023/8/16 -func (sd *SystemDao) GetTableInfo(dbInstance *gorm.DB, database string, tableName string) ([]*ColumnInfo, error) { +func (sd *SystemDao) GetTableInfo(dbInstance *gorm.DB, database string, tableName string) ([]*define.ColumnInfo, error) { var ( - list []*ColumnInfo + list []*define.ColumnInfo err error ) diff --git a/wrapper_db_client.go b/wrapper_db_client.go index 958ffd0..ee0885d 100644 --- a/wrapper_db_client.go +++ b/wrapper_db_client.go @@ -1,4 +1,4 @@ -// Package define ... +// Package database ... // // Description : define ... // @@ -9,6 +9,7 @@ package database import ( "context" + "errors" "fmt" "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/database/define" @@ -18,6 +19,8 @@ import ( "gorm.io/driver/sqlite" "gorm.io/gorm" gormLogger "gorm.io/gorm/logger" + "sync" + "time" ) // DBClient 包装日志实例 @@ -26,12 +29,15 @@ import ( // // Date : 3:09 PM 2021/12/24 type DBClient struct { - DbFlag string // 数据库标识 - LoggerInstance *zap.Logger // 日志实例 - master *gorm.DB // 主库 - slave *gorm.DB // 从库 - ExtraFieldList []string // 提取的字段 - Cfg define.Driver // 数据库配置 + DbFlag string // 数据库标识 + LoggerInstance *zap.Logger // 日志实例 + master *gorm.DB // 主库 + slave *gorm.DB // 从库 + ExtraFieldList []string // 提取的字段 + Cfg define.Driver // 数据库配置 + cacheTableStructureConfig *define.CacheTableStructureConfig // 缓存配置 + lock *sync.RWMutex // 操作锁 + tableStructureCache map[string][]*define.ColumnInfo // 表结构缓存 } // Init 初始化客户端 @@ -39,7 +45,9 @@ type DBClient struct { // Author : go_developer@163.com<白茶清欢> // // Date : 17:44 2024/8/20 -func (dc *DBClient) Init(databaseConfig *define.Database) error { +func (dc *DBClient) Init(databaseConfig *define.Database, cacheTableStructureConfig *define.CacheTableStructureConfig) error { + dc.lock = &sync.RWMutex{} + dc.cacheTableStructureConfig = cacheTableStructureConfig var err error if dc.master, err = dc.GetDatabaseClient(databaseConfig.Master, dc.LoggerInstance); nil != err { return err @@ -47,6 +55,22 @@ func (dc *DBClient) Init(databaseConfig *define.Database) error { if dc.slave, err = dc.GetDatabaseClient(databaseConfig.Slave, dc.LoggerInstance); nil != err { return err } + if err = dc.syncDbTableStructure(false); nil != err { // 同步缓存表结构 + return err + } + // 启动异步任务 + go func() { + if !dc.CacheDataTableStructureConfig().Enable { + // 未启用 + return + } + for { + select { + case <-time.After(time.Second * time.Duration(dc.CacheDataTableStructureConfig().SyncTimeInterval)): + _ = dc.syncDbTableStructure(true) + } + } + }() return nil } @@ -134,3 +158,70 @@ func (dc *DBClient) buildConnectionDSN(conf *define.Driver) string { conf.Timezone, ) } + +// CacheDataTableStructureConfig ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:03 2024/8/21 +func (dc *DBClient) CacheDataTableStructureConfig() *define.CacheTableStructureConfig { + if nil == dc.cacheTableStructureConfig { + return &define.CacheTableStructureConfig{Enable: false, SyncTimeInterval: 3600} + } + if dc.cacheTableStructureConfig.SyncTimeInterval <= 0 { + dc.cacheTableStructureConfig.SyncTimeInterval = 3600 + } + return dc.cacheTableStructureConfig +} + +// GetTableFieldList 获取表结构配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:07 2024/8/21 +func (dc *DBClient) GetTableFieldList(tableName string) ([]*define.ColumnInfo, error) { + if !dc.CacheDataTableStructureConfig().Enable { + // 未启用缓存, 返回空list + return make([]*define.ColumnInfo, 0), nil + } + dc.lock.RLock() + defer dc.lock.RUnlock() + if _, exist := dc.tableStructureCache[tableName]; !exist { + return nil, errors.New(tableName + " : cache result not found") + } + return dc.tableStructureCache[tableName], nil +} + +// syncDbTableStructure 缓存表结构 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:17 2024/8/21 +func (dc *DBClient) syncDbTableStructure(ignoreErr bool) error { + var ( + err error + tableList []string + ) + + c := dc.GetMaster(context.Background()) + systemDao := &SystemDao{} + if tableList, err = systemDao.GetTableList(c); nil != err { + return err + } + tableStructCache := make(map[string][]*define.ColumnInfo) + for _, itemTableName := range tableList { + fieldList, loadTableErr := systemDao.GetTableInfo(c, dc.Cfg.Database, itemTableName) + if nil != loadTableErr { + if ignoreErr { + continue + } + return loadTableErr + } + tableStructCache[itemTableName] = fieldList + } + // 更新缓存结果 + dc.lock.Lock() + defer dc.lock.Unlock() + dc.tableStructureCache = tableStructCache + return nil +}