🐛 Fix concurrent write and read auth context cache

This commit is contained in:
LittleSheep 2024-07-17 13:27:16 +08:00
parent 7b9aebd5d7
commit 7436d4b2cc

View File

@ -12,10 +12,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
var ( var authContextCache sync.Map
authContextMutex sync.Mutex
authContextCache = make(map[string]models.AuthContext)
)
func Authenticate(atk, rtk string, rty int) (ctx models.AuthContext, perms map[string]any, newAtk, newRtk string, err error) { func Authenticate(atk, rtk string, rty int) (ctx models.AuthContext, perms map[string]any, newAtk, newRtk string, err error) {
var claims PayloadClaims var claims PayloadClaims
@ -52,12 +49,10 @@ func GetAuthContext(jti string) (models.AuthContext, error) {
var err error var err error
var ctx models.AuthContext var ctx models.AuthContext
if val, ok := authContextCache[jti]; ok { if val, ok := authContextCache.Load(jti); ok {
ctx = val ctx = val.(models.AuthContext)
ctx.LastUsedAt = time.Now() ctx.LastUsedAt = time.Now()
authContextMutex.Lock() authContextCache.Store(jti, ctx)
authContextCache[jti] = ctx
authContextMutex.Unlock()
} else { } else {
ctx, err = CacheAuthContext(jti) ctx, err = CacheAuthContext(jti)
log.Debug().Str("jti", jti).Msg("Created a new auth context cache") log.Debug().Str("jti", jti).Msg("Created a new auth context cache")
@ -89,36 +84,32 @@ func CacheAuthContext(jti string) (models.AuthContext, error) {
} }
// Put the data into memory for cache // Put the data into memory for cache
authContextMutex.Lock() authContextCache.Store(jti, ctx)
authContextCache[jti] = ctx
authContextMutex.Unlock()
return ctx, nil return ctx, nil
} }
func RecycleAuthContext() { func RecycleAuthContext() {
if len(authContextCache) == 0 {
return
}
affected := 0 affected := 0
for key, val := range authContextCache {
authContextCache.Range(func(key, value any) bool {
val := value.(models.AuthContext)
if val.LastUsedAt.Add(60*time.Second).Unix() < time.Now().Unix() { if val.LastUsedAt.Add(60*time.Second).Unix() < time.Now().Unix() {
affected++ affected++
authContextMutex.Lock() authContextCache.Delete(key)
delete(authContextCache, key)
authContextMutex.Unlock()
} }
} return true
})
log.Debug().Int("affected", affected).Msg("Recycled auth context...") log.Debug().Int("affected", affected).Msg("Recycled auth context...")
} }
func InvalidAuthCacheWithUser(userId uint) { func InvalidAuthCacheWithUser(userId uint) {
for key, val := range authContextCache { authContextCache.Range(func(key, value any) bool {
val := value.(models.AuthContext)
if val.Account.ID == userId { if val.Account.ID == userId {
authContextMutex.Lock() authContextCache.Delete(key)
delete(authContextCache, key)
authContextMutex.Unlock()
} }
} return true
})
} }