package model import ( "fmt" "reflect" "sync" "qoobing.com/gomod/gorm" "qoobing.com/gomod/log" "qoobing.com/gomod/redis" ) var ( modelsDb = map[string]*modelDb{} modelsRedis = map[string]*modelRedis{} defaultDbName = "" defaultRedisName = "" errNoModelFound = errorsWrap("named model(%s) not found") errModeAlreadyInit = errorsWrap("named model(%s) already initilized") errOpenDBFailed = errorsWrap("open database failed: %s") errOpenRedisFailed = errorsWrap("open redis failed: %s") errUnknownModelType = errorsWrap("unknown model type: %s") ) func errorsWrap(base string) func(...any) error { return func(v ...any) error { return fmt.Errorf(base, v...) } } type ( DbConfig = gorm.Config RedisConfig = redis.Config Configurable interface { *DbConfig | *RedisConfig } ) type ( modelDb struct { mu sync.Mutex db *gorm.DB dbCfg *gorm.Config } modelRedis struct { mu sync.Mutex redis redis.Conn redisCfg *redis.Config redisPool *redis.Pool } ) // Init init named database config & redis config func Init[Config Configurable](name string, cfg Config) error { var ( dbCfg *gorm.Config redisCfg *redis.Config inCfgType = reflect.TypeOf(cfg) ) if inCfgType == reflect.TypeOf(dbCfg) { dbCfg = reflect.ValueOf(cfg).Interface().(*gorm.Config) _, ok := modelsDb[name] if ok { return errModeAlreadyInit("db:" + name) } db, err := gorm.NewDB(*dbCfg) if err != nil { return errOpenDBFailed(err) } modelsDb[name] = &modelDb{ db: db, dbCfg: dbCfg, } if defaultDbName == "" || (defaultDbName != "" && name == "default") { defaultDbName = name } log.Infof("success init model(%s) database:%s", name, dbCfg.GetSecDsn()) return nil } if inCfgType == reflect.TypeOf(redisCfg) { redisCfg = reflect.ValueOf(cfg).Interface().(*redis.Config) _, ok := modelsRedis[name] if ok { return errModeAlreadyInit("redis:" + name) } redisPool := redis.NewPool(*redisCfg) if redisPool == nil { return errOpenRedisFailed("new redis pool return nil") } modelsRedis[name] = &modelRedis{ redisPool: redisPool, redisCfg: redisCfg, } if defaultRedisName == "" || (defaultRedisName != "" && name == "default") { defaultRedisName = name } log.Infof("success init model(%s) database:%s", name, redisCfg.GetSecDsn()) return nil } log.Infof("failed init model(%s), unknown model type: %s", name, inCfgType.Name()) return errUnknownModelType(inCfgType.Name()) } func Db() *gorm.DB { return DbOf(defaultDbName) } func DbOf(name string) *gorm.DB { m, ok := modelsDb[name] if !ok { panic(errNoModelFound(name)) } return gorm.NewSession(m.db) } func Redis() redis.Conn { return RedisOf(defaultRedisName) } func RedisOf(name string) redis.Conn { m, ok := modelsRedis[name] if !ok { panic(errNoModelFound(name)) } return m.redisPool.Get() } func RedisPool() *redis.Pool { return RedisPoolOf(defaultRedisName) } func RedisPoolOf(name string) *redis.Pool { m, ok := modelsRedis[name] if !ok { panic(errNoModelFound(name)) } return m.redisPool }