// cleanup.go — background expiration of temporary whitelisted IPs // // The cleanup goroutine runs every cfg.CleanupInterval and removes entries // from the temporary whitelist whose TTL has elapsed. // // Why not use a persistent store (Redis, SQLite)? // // - TTL-based expiry with a map + periodic cleanup is simpler and has // no external dependencies. // - For most use cases (a handful of IPs), this is perfectly adequate. // - If you need persistence across restarts, add a disk-backed store later. // // Why a goroutine instead of checking expiry on every request? // // - Checking expiry on every request adds latency (two map lookups per request). // - The cleanup goroutine is a one-time cost that keeps the hot path fast. // - The cleanup runs in a separate goroutine so it doesn't block requests. package main import ( "log" "time" ) // cleanupLoop runs a periodic cleanup of the temporary whitelist. // // It runs every d seconds and removes entries that have expired. // The loop stops when the context is cancelled. func cleanupLoop(tw *tempWhitelist, d time.Duration) { ticker := time.NewTicker(d) defer ticker.Stop() for { select { case <-ticker.C: now := time.Now() tw.mu.Lock() for ip, entry := range tw.entries { if entry.Expires.Before(now) { log.Printf("expired temporary whitelist for %s", ip) delete(tw.entries, ip) } } tw.mu.Unlock() } } }