diff --git a/cache.go b/cache.go index 43f09fc..5619391 100644 --- a/cache.go +++ b/cache.go @@ -37,6 +37,10 @@ type Cache struct { // maxSize is the maximum number of items allowed in the cache. maxSize int + // autoCleanupInterval defines how often Cleanup is called automatically. + autoCleanupInterval time.Duration + // stopCleanup channel to terminate the auto cleanup goroutine. + stopCleanup chan struct{} } // DefaultMaxSize is the default maximum number of items in the cache. @@ -44,12 +48,16 @@ const DefaultMaxSize = 500 // NewCache creates a new empty cache instance that is ready for use. func NewCache() *Cache { - return &Cache{ - items: make(map[string]CacheItem, DefaultMaxSize), - order: list.New(), - elems: make(map[string]*list.Element, DefaultMaxSize), - maxSize: DefaultMaxSize, + c := &Cache{ + items: make(map[string]CacheItem, DefaultMaxSize), + order: list.New(), + elems: make(map[string]*list.Element, DefaultMaxSize), + maxSize: DefaultMaxSize, + autoCleanupInterval: 5 * time.Minute, + stopCleanup: make(chan struct{}), } + go c.startAutoCleanup() + return c } // Set adds or updates an item in the cache with the specified expiration duration. @@ -167,3 +175,22 @@ func (c *Cache) removeItem(key string) { delete(c.elems, key) } } + +// startAutoCleanup initiates a goroutine that periodically cleans up expired cache items. +func (c *Cache) startAutoCleanup() { + ticker := time.NewTicker(c.autoCleanupInterval) + for { + select { + case <-ticker.C: + c.Cleanup() + case <-c.stopCleanup: + ticker.Stop() + return + } + } +} + +// Close terminates the auto cleanup goroutine. +func (c *Cache) Close() { + close(c.stopCleanup) +} diff --git a/metadata_cache.go b/metadata_cache.go index 018691c..38cfa81 100644 --- a/metadata_cache.go +++ b/metadata_cache.go @@ -7,16 +7,21 @@ import ( "time" ) -// MetadataCache provides thread-safe caching for OIDC provider metadata type MetadataCache struct { - metadata *ProviderMetadata - expiresAt time.Time - mutex sync.RWMutex + metadata *ProviderMetadata + expiresAt time.Time + mutex sync.RWMutex + autoCleanupInterval time.Duration + stopCleanup chan struct{} } -// NewMetadataCache creates a new metadata cache instance func NewMetadataCache() *MetadataCache { - return &MetadataCache{} + c := &MetadataCache{ + autoCleanupInterval: 5 * time.Minute, + stopCleanup: make(chan struct{}), + } + go c.startAutoCleanup() + return c } // Cleanup removes expired metadata from the cache. @@ -60,14 +65,32 @@ func (c *MetadataCache) GetMetadata(providerURL string, httpClient *http.Client, c.metadata = metadata // Calculate expiration time based on usage patterns -usageCount := 0 // This should be replaced with actual usage tracking logic -if usageCount < 10 { - c.expiresAt = time.Now().Add(30 * time.Minute) -} else if usageCount < 50 { - c.expiresAt = time.Now().Add(1 * time.Hour) -} else { - c.expiresAt = time.Now().Add(2 * time.Hour) -} + usageCount := 0 // This should be replaced with actual usage tracking logic + if usageCount < 10 { + c.expiresAt = time.Now().Add(30 * time.Minute) + } else if usageCount < 50 { + c.expiresAt = time.Now().Add(1 * time.Hour) + } else { + c.expiresAt = time.Now().Add(2 * time.Hour) + } + // End of GetMetadata return metadata, nil } + +func (c *MetadataCache) startAutoCleanup() { + ticker := time.NewTicker(c.autoCleanupInterval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + c.Cleanup() + case <-c.stopCleanup: + return + } + } +} + +func (c *MetadataCache) Close() { + close(c.stopCleanup) +}