go_dreamfactory/modules/model_comp.go
2022-06-17 16:34:09 +08:00

259 lines
7.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 modules
import (
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/sys/mgo"
"go_dreamfactory/lego/sys/redis"
"go_dreamfactory/sys/cache"
"go_dreamfactory/sys/db"
"reflect"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"google.golang.org/protobuf/proto"
)
/*
基础组件 缓存组件 读写缓存数据
DB组件也封装进来
*/
type Model_Comp struct {
cbase.ModuleCompBase
Redis redis.ISys
DB mgo.ISys
TableName string //redis key前缀
}
const (
DB_ModelTable core.SqlTable = "model_log"
)
//组件初始化接口
func (this *Model_Comp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
this.ModuleCompBase.Init(service, module, comp, options)
this.Redis = cache.Redis()
this.DB = db.Mgo()
return
}
func (this *Model_Comp) Start() (err error) {
err = this.ModuleCompBase.Start()
return
}
func (this *Model_Comp) ukey(uid string) string {
return fmt.Sprintf("%s:%s", this.TableName, uid)
}
func (this *Model_Comp) InsertModelLogs(table string, uID string, target interface{}) (err error) {
data := &comm.Autogenerated{
ID: primitive.NewObjectID().Hex(),
UID: uID,
Act: string(comm.LogHandleType_Insert),
}
data.D = append(data.D, table) // D[0]
data.D = append(data.D, target) // D[1]
_, err = this.DB.InsertOne(DB_ModelTable, data)
if err != nil {
log.Errorf("insert model db err %v", err)
}
return err
}
func (this *Model_Comp) DeleteModelLogs(table string, uID string, where interface{}) (err error) {
data := &comm.Autogenerated{
ID: primitive.NewObjectID().Hex(),
UID: uID,
Act: string(comm.LogHandleType_Delete),
}
data.D = append(data.D, table) // D[0]
data.D = append(data.D, where) // D[1]
_, err = this.DB.InsertOne(DB_ModelTable, data)
if err != nil {
log.Errorf("insert model db err %v", err)
}
return err
}
func (this *Model_Comp) UpdateModelLogs(table string, uID string, where bson.M, target interface{}) (err error) {
data := &comm.Autogenerated{
ID: primitive.NewObjectID().Hex(),
UID: uID,
Act: string(comm.LogHandleType_Update),
}
data.D = append(data.D, table) // D[0]
data.D = append(data.D, where) // D[1]
data.D = append(data.D, target) // D[2]
_, err = this.DB.InsertOne(DB_ModelTable, data)
if err != nil {
log.Errorf("insert model db err %v", err)
}
return err
}
//设置缓存JSON格式数据
//data 值允许protobuf格式的对象
// attrs 操作可选项目 eg.传入WithDisabledMgoLog() 表示关闭日志,否则开启;WithND() 传入表示插入操作不传表示更新前提不能传入传入WithDisabledMgoLog()
func (this *Model_Comp) SetObj(uid string, data proto.Message, attrs ...*cache.OperationAttr) error {
expr := cache.OperationAttrs(attrs).Find(cache.ATTR_EXPIRE).Unwrap_Or(time.Second * 0).(time.Duration)
err := this.Redis.Set(this.ukey(uid), data, expr)
if err != nil {
log.Errorf("set err:%v", err)
return err
}
return this.logOpt(uid, data, attrs...)
}
//缓存多个字段的数据 data参数 允许map或protobuf
//eg.map[string]*TestData{"li_1": {Name: "liwei2dao", Agr: 56}, "li_2": {Name: "liwei3dao", Agr: 78}}
//or &TestData{Name: "liwei1dao", Agr: 12, Sub: &TestAny{SubName: "test", Age: 20}}
// attrs 操作可选项目 eg.传入WithDisabledMgoLog() 表示关闭日志,否则开启;WithND() 传入表示插入操作不传表示更新前提不能传入传入WithDisabledMgoLog()
//如果更新数据uid作为where条件之一如果检索结果不能确定唯一此时data 必需是map[string]interface{}类型必需包含_id 字段
func (this *Model_Comp) SetHM(uid string, data interface{}, attrs ...*cache.OperationAttr) error {
err := this.Redis.HMSet(this.ukey(uid), data)
if err != nil {
log.Errorf("SetHM err: %v", err)
return err
}
return this.logOpt(uid, data, attrs...)
}
//缓存一个字段的数据
//如果更新数据uid作为where条件之一如果检索结果不能确定唯一此时data 必需是map[string]interface{}类型必需包含_id 字段
func (this *Model_Comp) SetH(uid string, field string, data interface{}, attrs ...*cache.OperationAttr) error {
err := this.Redis.HSet(this.ukey(uid), field, data)
if err != nil {
log.Errorf("SetH err %v", err)
return err
}
return this.logOpt(uid, data, attrs...)
}
//获取缓存JSON数据
func (this *Model_Comp) GetObj(uid string, v proto.Message) error {
err := this.Redis.Get(this.ukey(uid), v)
if err != nil {
if err == redis.RedisNil {
//query from mgo
err = this.DB.FindOne(core.SqlTable(this.TableName), bson.M{"_id": uid}).Decode(v)
if err != nil {
//no record
if err == mongo.ErrNoDocuments {
_, err = this.DB.InsertOne(core.SqlTable(this.TableName), v)
if err != nil {
log.Errorf("insert err: %v", err)
return err
}
//set cache
return this.SetObj(uid, v, cache.WithND())
}
}
} else {
log.Errorf("get cache err: %v", err)
}
}
return err
}
//获取对象所有字段数据
//data类型map或protobuf
func (this *Model_Comp) GetHM(uid string, data interface{}) error {
ok, err := this.Redis.ExistsKey(this.ukey(uid))
if err != nil {
log.Errorf("key no exist %v", this.ukey(uid))
return err
}
if ok {
return this.Redis.HGetAll(this.ukey(uid), data)
} else {
filter := bson.M{"uid": uid}
c, err2 := this.DB.Find(core.SqlTable(this.TableName), filter)
if err2 != nil {
log.Errorf("GetHM-find err:%v", err)
return err
}
err2 = c.Decode(data)
if err2 != nil {
log.Errorf("GetHM-find decode err:%v", err)
return err
}
//update cache without mgolog
return this.SetHM(this.ukey(uid), data, cache.WithDisabledMgoLog())
}
}
//获取字段数据 缓存存储的数据为hashmap时
func (this *Model_Comp) GetH(uid string, field string, v interface{}) error {
return this.Redis.HGet(this.ukey(uid), field, v)
}
//删除一条数据
func (this *Model_Comp) DelH(uid string) error {
err := this.Redis.HDel(this.ukey(uid))
if err != nil {
log.Errorf("del err:%v", err)
return err
}
return this.DeleteModelLogs(this.TableName, uid, bson.M{"uid": uid})
}
//删除缓存字段
func (this *Model_Comp) DelHF(uid string, fields ...string) error {
err := this.Redis.HDel(this.ukey(uid), fields...)
if err != nil {
log.Errorf("DelHF err: %v", err)
return err
}
//get new data after delete
data := make(map[string]interface{})
err = this.Redis.HGetAll(this.ukey(uid), data)
if err != nil {
log.Errorf("DelHF-HGetAll err: %v", err)
return err
}
//cache with mgolog
return this.SetHM(this.ukey(uid), data)
}
//日志操作可选项
func (this *Model_Comp) logOpt(uid string, data interface{}, attrs ...*cache.OperationAttr) error {
ret := cache.OperationAttrs(attrs).Find(cache.ATTR_MGOLOG).Unwrap_Or(nil)
if ret == nil { //启用mgolog
ir := cache.OperationAttrs(attrs).Find(cache.ATTR_INSERT).Unwrap_Or(nil)
if ir == nil { //updte opt
where := bson.M{"uid": uid}
if reflect.ValueOf(data).Kind() == reflect.Map {
if m, ok := data.(map[string]interface{}); ok {
where["_id"] = m["_id"]
} else {
return fmt.Errorf("have %v,but want map[string]interface{}", data)
}
}
return this.UpdateModelLogs(this.TableName, uid, where, data)
} else { //insert opt
return this.InsertModelLogs(this.TableName, uid, data)
}
}
return nil
}