259 lines
7.4 KiB
Go
259 lines
7.4 KiB
Go
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
|
||
}
|