🐛 Fix concurrent write and read auth context cache
This commit is contained in:
		@@ -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
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user