2025-01-21 14:02:43 +00:00
|
|
|
package cache
|
2024-11-26 17:21:41 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2025-01-21 14:02:43 +00:00
|
|
|
DiskUsage = NewCache(30*time.Second, 24*time.Hour)
|
|
|
|
RealPath = NewCache(48*time.Hour, 72*time.Hour)
|
|
|
|
SearchResults = NewCache(15*time.Second, time.Hour)
|
|
|
|
OnlyOffice = NewCache(48*time.Hour, 1*time.Hour)
|
2024-11-26 17:21:41 +00:00
|
|
|
)
|
|
|
|
|
2025-01-21 14:02:43 +00:00
|
|
|
func NewCache(expires time.Duration, cleanup time.Duration) *KeyCache {
|
2024-11-26 17:21:41 +00:00
|
|
|
newCache := KeyCache{
|
|
|
|
data: make(map[string]cachedValue),
|
|
|
|
expiresAfter: expires, // default
|
|
|
|
}
|
|
|
|
go newCache.cleanupExpiredJob(cleanup)
|
|
|
|
return &newCache
|
|
|
|
}
|
|
|
|
|
|
|
|
type KeyCache struct {
|
|
|
|
data map[string]cachedValue
|
|
|
|
mu sync.RWMutex
|
|
|
|
expiresAfter time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
type cachedValue struct {
|
|
|
|
value interface{}
|
|
|
|
expiresAt time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *KeyCache) Set(key string, value interface{}) {
|
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
c.data[key] = cachedValue{
|
|
|
|
value: value,
|
|
|
|
expiresAt: time.Now().Add(c.expiresAfter),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-21 14:02:43 +00:00
|
|
|
func (c *KeyCache) Delete(key string) {
|
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
delete(c.data, key)
|
|
|
|
}
|
|
|
|
|
2024-11-26 17:21:41 +00:00
|
|
|
func (c *KeyCache) SetWithExp(key string, value interface{}, exp time.Duration) {
|
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
c.data[key] = cachedValue{
|
|
|
|
value: value,
|
|
|
|
expiresAt: time.Now().Add(exp),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *KeyCache) Get(key string) interface{} {
|
|
|
|
c.mu.RLock()
|
|
|
|
defer c.mu.RUnlock()
|
|
|
|
cached, ok := c.data[key]
|
|
|
|
if !ok || time.Now().After(cached.expiresAt) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return cached.value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *KeyCache) cleanupExpired() {
|
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
now := time.Now()
|
|
|
|
for key, cached := range c.data {
|
|
|
|
if now.After(cached.expiresAt) {
|
|
|
|
delete(c.data, key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// should automatically run for all cache types as part of init.
|
|
|
|
func (c *KeyCache) cleanupExpiredJob(frequency time.Duration) {
|
|
|
|
ticker := time.NewTicker(frequency)
|
|
|
|
defer ticker.Stop()
|
|
|
|
for range ticker.C {
|
|
|
|
c.cleanupExpired()
|
|
|
|
}
|
|
|
|
}
|