package executor import ( "crypto/sha256" "encoding/hex" "sync" "time") type userIDCacheEntry struct { value string expire time.Time} var ( userIDCache = make(map[string]userIDCacheEntry) userIDCacheMu sync.RWMutex userIDCacheCleanupOnce sync.Once) const ( userIDTTL = time.Hour userIDCacheCleanupPeriod = 15 * time.Minute) func startUserIDCacheCleanup() { go func() { ticker := time.NewTicker(userIDCacheCleanupPeriod) defer ticker.Stop() for range ticker.C { purgeExpiredUserIDs() } }()} func purgeExpiredUserIDs() { now := time.Now() userIDCacheMu.Lock() for key, entry := range userIDCache { if !entry.expire.After(now) { delete(userIDCache, key) } } userIDCacheMu.Unlock()} func userIDCacheKey(apiKey string) string { sum := sha256.Sum256([]byte(apiKey)) return hex.EncodeToString(sum[:])} func cachedUserID(apiKey string) string { if apiKey == "" { return generateFakeUserID() } userIDCacheCleanupOnce.Do(startUserIDCacheCleanup) key := userIDCacheKey(apiKey) now := time.Now() userIDCacheMu.RLock() entry, ok := userIDCache[key] valid := ok && entry.value != "" && entry.expire.After(now) && isValidUserID(entry.value) userIDCacheMu.RUnlock() if valid { userIDCacheMu.Lock() entry = userIDCache[key] if entry.value != "" && entry.expire.After(now) && isValidUserID(entry.value) { entry.expire = now.Add(userIDTTL) userIDCache[key] = entry userIDCacheMu.Unlock() return entry.value } userIDCacheMu.Unlock() } newID := generateFakeUserID() userIDCacheMu.Lock() entry, ok = userIDCache[key] if !ok || entry.value == "" || !entry.expire.After(now) || !isValidUserID(entry.value) { entry.value = newID } entry.expire = now.Add(userIDTTL) userIDCache[key] = entry userIDCacheMu.Unlock() return entry.value}
package executor
import (
"crypto/sha256"
"encoding/hex"
"sync"
"time"
)
type userIDCacheEntry struct {
value string
expire time.Time
}
var (
userIDCache = make(map[string]userIDCacheEntry)
userIDCacheMu sync.RWMutex
userIDCacheCleanupOnce sync.Once
)
const (
userIDTTL = time.Hour
userIDCacheCleanupPeriod = 15 * time.Minute
)
func startUserIDCacheCleanup() {
go func() {
ticker := time.NewTicker(userIDCacheCleanupPeriod)
defer ticker.Stop()
for range ticker.C {
purgeExpiredUserIDs()
}
}()
}
func purgeExpiredUserIDs() {
now := time.Now()
userIDCacheMu.Lock()
for key, entry := range userIDCache {
if !entry.expire.After(now) {
delete(userIDCache, key)
}
}
userIDCacheMu.Unlock()
}
func userIDCacheKey(apiKey string) string {
sum := sha256.Sum256([]byte(apiKey))
return hex.EncodeToString(sum[:])
}
func cachedUserID(apiKey string) string {
if apiKey == "" {
return generateFakeUserID()
}
userIDCacheCleanupOnce.Do(startUserIDCacheCleanup)
key := userIDCacheKey(apiKey)
now := time.Now()
userIDCacheMu.RLock()
entry, ok := userIDCache[key]
valid := ok && entry.value != "" && entry.expire.After(now) && isValidUserID(entry.value)
userIDCacheMu.RUnlock()
if valid {
userIDCacheMu.Lock()
entry = userIDCache[key]
if entry.value != "" && entry.expire.After(now) && isValidUserID(entry.value) {
entry.expire = now.Add(userIDTTL)
userIDCache[key] = entry
userIDCacheMu.Unlock()
return entry.value
}
userIDCacheMu.Unlock()
}
newID := generateFakeUserID()
userIDCacheMu.Lock()
entry, ok = userIDCache[key]
if !ok || entry.value == "" || !entry.expire.After(now) || !isValidUserID(entry.value) {
entry.value = newID
}
entry.expire = now.Add(userIDTTL)
userIDCache[key] = entry
userIDCacheMu.Unlock()
return entry.value
}