Skip to content

Commit

Permalink
fix: fix key of singleflight not contains vars
Browse files Browse the repository at this point in the history
  • Loading branch information
asjdf authored Feb 24, 2023
1 parent 8f13c82 commit 3bc9436
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- 即插即用
- 旁路缓存
- 穿透防护
- 击穿防护
- 多存储介质(内存/redis)

## 使用说明
Expand Down
24 changes: 12 additions & 12 deletions cache/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ func (h *queryHandler) BeforeQuery() func(db *gorm.DB) {
db.InstanceSet("gorm:cache:vars", db.Statement.Vars)

if util.ShouldCache(tableName, cache.Config.Tables) {
hitted := false
hit := false
defer func() {
if hitted {
if hit {
cache.IncrHitCount()
} else {
cache.IncrMissCount()
}
}()

// singleFlight Check
singleFlightKey := fmt.Sprintf("%s:%s", tableName, sql) // todo: key with vars
singleFlightKey := util.GenSingleFlightKey(tableName, sql, db.Statement.Vars...)
h.singleFlight.mu.Lock()
if h.singleFlight.m == nil {
h.singleFlight.m = make(map[string]*call)
Expand All @@ -88,7 +88,7 @@ func (h *queryHandler) BeforeQuery() func(db *gorm.DB) {
_ = db.AddError(err)
return
}
hitted = true
hit = true
db.RowsAffected = c.rowsAffected
db.Error = multierror.Append(util.SingleFlightHit) // 为保证后续流程不走,必须设一个error
if c.err != nil {
Expand All @@ -103,7 +103,7 @@ func (h *queryHandler) BeforeQuery() func(db *gorm.DB) {
h.singleFlight.mu.Unlock()
db.InstanceSet("gorm:cache:query:single_flight_call", c)

tryPrimaryCache := func() (hitted bool) {
tryPrimaryCache := func() (hit bool) {
primaryKeys := getPrimaryKeysFromWhereClause(db)
cache.Logger.CtxInfo(ctx, "[BeforeQuery] parse primary keys = %v", primaryKeys)

Expand Down Expand Up @@ -150,11 +150,11 @@ func (h *queryHandler) BeforeQuery() func(db *gorm.DB) {
return
}
db.Error = util.PrimaryCacheHit
hitted = true
hit = true
return
}

trySearchCache := func() (hitted bool) {
trySearchCache := func() (hit bool) {
// search cache hit
cacheValue, err := cache.GetSearchCache(ctx, tableName, sql, db.Statement.Vars...)
if err != nil {
Expand All @@ -167,7 +167,7 @@ func (h *queryHandler) BeforeQuery() func(db *gorm.DB) {
cache.Logger.CtxInfo(ctx, "[BeforeQuery] get value: %s", cacheValue)
if cacheValue == "recordNotFound" { // 应对缓存穿透
db.Error = util.RecordNotFoundCacheHit
hitted = true
hit = true
return
}
rowsAffectedPos := strings.Index(cacheValue, "|")
Expand All @@ -184,19 +184,19 @@ func (h *queryHandler) BeforeQuery() func(db *gorm.DB) {
return
}
db.Error = util.SearchCacheHit
hitted = true
hit = true
return
}

if cache.Config.CacheLevel == config.CacheLevelAll || cache.Config.CacheLevel == config.CacheLevelOnlyPrimary {
if tryPrimaryCache() {
hitted = true
hit = true
return
}
}
if cache.Config.CacheLevel == config.CacheLevelAll || cache.Config.CacheLevel == config.CacheLevelOnlySearch {
if !hitted && trySearchCache() {
hitted = true
if !hit && trySearchCache() {
hit = true
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions util/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,17 @@ func GenSearchCacheKey(instanceId string, tableName string, sql string, vars ...
func GenSearchCachePrefix(instanceId string, tableName string) string {
return GormCachePrefix + ":" + instanceId + ":s:" + tableName
}

func GenSingleFlightKey(tableName string, sql string, vars ...interface{}) string {
buf := strings.Builder{}
buf.WriteString(sql)
for _, v := range vars {
pv := reflect.ValueOf(v)
if pv.Kind() == reflect.Ptr {
buf.WriteString(fmt.Sprintf(":%v", pv.Elem()))
} else {
buf.WriteString(fmt.Sprintf(":%v", v))
}
}
return fmt.Sprintf("%s:%s", tableName, buf.String())
}

0 comments on commit 3bc9436

Please sign in to comment.