refactor: move auth, GDPR, and booking cleanup to centralized scheduler
Convert CleanupRevokedJTIs to return (int, error) and remove StartJTICleanup goroutine. Add CleanupStaleLoginEntries and CleanupGDPRExportCache for centralized scheduler. Add clock.London timezone location. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -24,28 +24,20 @@ type gdprCacheEntry struct {
|
||||
generating bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
ticker := time.NewTicker(5 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Printf("Panic recovered in GDPR export cache cleanup ticker: %v", r)
|
||||
}
|
||||
}()
|
||||
gdprExportCacheMu.Lock()
|
||||
now := clock.Now()
|
||||
for k, v := range gdprExportCache {
|
||||
if now.After(v.expiresAt) {
|
||||
delete(gdprExportCache, k)
|
||||
}
|
||||
}
|
||||
gdprExportCacheMu.Unlock()
|
||||
}()
|
||||
// CleanupGDPRExportCache removes expired entries from the GDPR export cache.
|
||||
// Called by the centralised jobs scheduler.
|
||||
func CleanupGDPRExportCache(ctx context.Context) (int, error) {
|
||||
gdprExportCacheMu.Lock()
|
||||
defer gdprExportCacheMu.Unlock()
|
||||
now := clock.Now()
|
||||
var n int
|
||||
for k, v := range gdprExportCache {
|
||||
if now.After(v.expiresAt) {
|
||||
delete(gdprExportCache, k)
|
||||
n++
|
||||
}
|
||||
}()
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// GET /api/user/gdpr-export
|
||||
|
||||
@@ -1214,3 +1214,100 @@ func TestAnonymizeStaleGuestAccounts_DoesNotAffectRegisteredUsers(t *testing.T)
|
||||
t.Errorf("expected referral_code to be preserved, got %v", referralCode)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// CleanupGDPRExportCache Tests
|
||||
// ============================================================
|
||||
|
||||
func TestCleanupGDPRExportCache_Empty(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
gdprExportCacheMu.Lock()
|
||||
gdprExportCache = make(map[string]*gdprCacheEntry)
|
||||
gdprExportCacheMu.Unlock()
|
||||
|
||||
_, err := CleanupGDPRExportCache(context.Background())
|
||||
if err != nil {
|
||||
t.Errorf("expected nil error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupGDPRExportCache_RemovesExpired(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
gdprExportCacheMu.Lock()
|
||||
gdprExportCache = map[string]*gdprCacheEntry{
|
||||
"user-expired": {expiresAt: clock.Now().Add(-1 * time.Hour)},
|
||||
}
|
||||
gdprExportCacheMu.Unlock()
|
||||
|
||||
_, err := CleanupGDPRExportCache(context.Background())
|
||||
if err != nil {
|
||||
t.Errorf("expected nil error, got %v", err)
|
||||
}
|
||||
|
||||
gdprExportCacheMu.RLock()
|
||||
_, exists := gdprExportCache["user-expired"]
|
||||
gdprExportCacheMu.RUnlock()
|
||||
if exists {
|
||||
t.Error("expected expired entry to be removed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupGDPRExportCache_PreservesValid(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
gdprExportCacheMu.Lock()
|
||||
gdprExportCache = map[string]*gdprCacheEntry{
|
||||
"user-valid": {expiresAt: clock.Now().Add(1 * time.Hour)},
|
||||
}
|
||||
gdprExportCacheMu.Unlock()
|
||||
|
||||
_, err := CleanupGDPRExportCache(context.Background())
|
||||
if err != nil {
|
||||
t.Errorf("expected nil error, got %v", err)
|
||||
}
|
||||
|
||||
gdprExportCacheMu.RLock()
|
||||
entry, exists := gdprExportCache["user-valid"]
|
||||
gdprExportCacheMu.RUnlock()
|
||||
if !exists {
|
||||
t.Fatal("expected valid entry to be preserved")
|
||||
}
|
||||
if entry == nil {
|
||||
t.Error("expected non-nil entry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupGDPRExportCache_Mixed(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
gdprExportCacheMu.Lock()
|
||||
gdprExportCache = map[string]*gdprCacheEntry{
|
||||
"user-expired": {expiresAt: clock.Now().Add(-2 * time.Hour)},
|
||||
"user-valid": {expiresAt: clock.Now().Add(2 * time.Hour)},
|
||||
"user-expired2": {expiresAt: clock.Now().Add(-30 * time.Minute)},
|
||||
}
|
||||
gdprExportCacheMu.Unlock()
|
||||
|
||||
_, err := CleanupGDPRExportCache(context.Background())
|
||||
if err != nil {
|
||||
t.Errorf("expected nil error, got %v", err)
|
||||
}
|
||||
|
||||
gdprExportCacheMu.RLock()
|
||||
_, expiredExists := gdprExportCache["user-expired"]
|
||||
_, validExists := gdprExportCache["user-valid"]
|
||||
_, expired2Exists := gdprExportCache["user-expired2"]
|
||||
gdprExportCacheMu.RUnlock()
|
||||
|
||||
if expiredExists {
|
||||
t.Error("expected user-expired to be removed")
|
||||
}
|
||||
if expired2Exists {
|
||||
t.Error("expected user-expired2 to be removed")
|
||||
}
|
||||
if !validExists {
|
||||
t.Error("expected user-valid to be preserved")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user