代码拉取完成,页面将自动刷新
package gcache
import (
"encoding/json"
"fmt"
"gorm.io/gorm"
"gorm.io/gorm/callbacks"
"reflect"
"strings"
"time"
)
type Model interface{}
type JsonSearch struct {
PrimaryKeys []string `json:"primary_keys"`
}
func (e *Engine) BeforeQuery(tx *gorm.DB) {
for _, clauses := range tx.Statement.BuildClauses {
if c, ok := tx.Statement.Clauses[clauses]; ok {
if b, ok := tx.Statement.ClauseBuilders[clauses]; ok {
b(c, tx.Statement)
} else {
c.Build(tx.Statement)
}
}
}
// Redis 获取数据
sqlStr := generateKey(tx.Statement.SQL.String())
vars := make([]string, 0)
for _, elem := range tx.Statement.Vars {
vars = append(vars, fmt.Sprintf("%v", elem))
}
paramStr := generateKey(strings.Join(vars, "_"))
tx.Statement.SQL = strings.Builder{}
tx.Statement.Vars = []interface{}{}
if tx.Statement.Joins != nil {
e.opt.Logger.Info("存在Join方法,跳过缓存")
return
}
searchKey := getSearchKey(tx.Statement.Table, sqlStr, paramStr)
tx.InstanceSet("gorm:cache:searchKey", searchKey)
e.opt.Logger.Info(searchKey)
// 获取主键信息
row, err := e.rdb.Get(tx.Statement.Context, searchKey).Result()
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
if row == "" {
tx.RowsAffected = -1
return
}
searchInfo := &JsonSearch{}
err = json.Unmarshal([]byte(row), searchInfo)
if err != nil {
return
}
modelKeys := make([]string, 0)
for _, primaryKey := range searchInfo.PrimaryKeys {
modelKeys = append(modelKeys, getModelKey(tx.Statement.Table, primaryKey))
}
models, err := e.rdb.MGet(tx.Statement.Context, modelKeys...).Result()
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
// 判断是否获取到所有数据
for _, model := range models {
if model == nil {
e.opt.Logger.Info("缓存数据不全,跳过缓存")
return
}
}
callbacks.BuildQuerySQL(tx)
var cacheValues []string
for _, model := range models {
cacheValues = append(cacheValues, model.(string))
}
finalValue := ""
destKind := reflect.Indirect(reflect.ValueOf(tx.Statement.Dest)).Kind()
if destKind == reflect.Struct && len(cacheValues) == 1 {
finalValue = cacheValues[0]
} else if (destKind == reflect.Array || destKind == reflect.Slice) && len(cacheValues) >= 1 {
finalValue = "[" + strings.Join(cacheValues, ",") + "]"
}
tx.Statement.RowsAffected = int64(len(cacheValues))
err = json.Unmarshal([]byte(finalValue), tx.Statement.Dest)
tx.Error = PrimaryCacheHit
e.opt.Logger.Info(fmt.Sprint(tx.Statement.Dest))
}
func (e *Engine) AfterQuery(tx *gorm.DB) {
if tx.Error == PrimaryCacheHit {
tx.Error = nil
e.opt.Logger.Info("命中缓存:", tx.Statement.Table)
return
}
// Redis 获取数据
hsetKeyObj, ok := tx.InstanceGet("gorm:cache:searchKey")
if !ok {
return
}
hsetKey := hsetKeyObj.(string)
// 写入缓存
primaryKeys, objectMap := getObjectsAfterLoad(tx)
e.opt.Logger.Info(fmt.Sprint(primaryKeys))
e.opt.Logger.Info(fmt.Sprint(objectMap))
//tx.ScanRows()
pipeline := e.rdb.Pipeline()
searchModel := JsonSearch{PrimaryKeys: primaryKeys}
searchJson, err := json.Marshal(searchModel)
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
pipeline.Set(tx.Statement.Context, hsetKey, searchJson, e.opt.Expires)
for key, value := range objectMap {
modelJson, err := json.Marshal(value)
if err != nil {
e.opt.Logger.Error(err.Error())
return
}
modelKey := getModelKey(tx.Statement.Table, key)
pipeline.Set(tx.Statement.Context, modelKey, modelJson, e.opt.Expires+time.Second+3)
}
_, err = pipeline.Exec(tx.Statement.Context)
if err != nil {
e.opt.Logger.Error(err.Error())
}
}
// key的种类
// model model-primaryKey
// hash过期时间 model-EXPIRE-column
// where条件缓存 model-where-whereInfo{ whereValue:primaryList }
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。