Spaces:
Paused
Paused
| package helps | |
| 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 | |
| } | |