89 lines · 1.8 KB · Go
RawDownload
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}