- Implemented TUI auto-select for automated testing - Fixed TUI automation: autoSelectMsg handling in Update() - Auto-database selection in DatabaseSelector - Created focused test suite (test_as_postgres.sh) - Created retention policy test (test_retention.sh) - All 10 security tests passing Features validated: ✅ Backup retention policy (30 days, min backups) ✅ Rate limiting (exponential backoff) ✅ Privilege checks (root detection) ✅ Resource limit validation ✅ Path sanitization ✅ Checksum verification (SHA-256) ✅ Audit logging ✅ Secure permissions ✅ Configuration persistence ✅ TUI automation framework Test results: 10/10 passed Backup files created with .dump, .sha256, .info Retention cleanup verified (old files removed)
83 lines
1.8 KiB
Go
Executable File
83 lines
1.8 KiB
Go
Executable File
package checks
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// cacheEntry holds cached disk space information with TTL
|
|
type cacheEntry struct {
|
|
check *DiskSpaceCheck
|
|
timestamp time.Time
|
|
}
|
|
|
|
// DiskSpaceCache provides thread-safe caching of disk space checks with TTL
|
|
type DiskSpaceCache struct {
|
|
cache map[string]*cacheEntry
|
|
cacheTTL time.Duration
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// NewDiskSpaceCache creates a new disk space cache with specified TTL
|
|
func NewDiskSpaceCache(ttl time.Duration) *DiskSpaceCache {
|
|
if ttl <= 0 {
|
|
ttl = 30 * time.Second // Default 30 second cache
|
|
}
|
|
|
|
return &DiskSpaceCache{
|
|
cache: make(map[string]*cacheEntry),
|
|
cacheTTL: ttl,
|
|
}
|
|
}
|
|
|
|
// Get retrieves cached disk space check or performs new check if cache miss/expired
|
|
func (c *DiskSpaceCache) Get(path string) *DiskSpaceCheck {
|
|
c.mu.RLock()
|
|
if entry, exists := c.cache[path]; exists {
|
|
if time.Since(entry.timestamp) < c.cacheTTL {
|
|
c.mu.RUnlock()
|
|
return entry.check
|
|
}
|
|
}
|
|
c.mu.RUnlock()
|
|
|
|
// Cache miss or expired - perform new check
|
|
check := CheckDiskSpace(path)
|
|
|
|
c.mu.Lock()
|
|
c.cache[path] = &cacheEntry{
|
|
check: check,
|
|
timestamp: time.Now(),
|
|
}
|
|
c.mu.Unlock()
|
|
|
|
return check
|
|
}
|
|
|
|
// Clear removes all cached entries
|
|
func (c *DiskSpaceCache) Clear() {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.cache = make(map[string]*cacheEntry)
|
|
}
|
|
|
|
// Cleanup removes expired entries (call periodically)
|
|
func (c *DiskSpaceCache) Cleanup() {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
now := time.Now()
|
|
for path, entry := range c.cache {
|
|
if now.Sub(entry.timestamp) >= c.cacheTTL {
|
|
delete(c.cache, path)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Global cache instance with 30-second TTL
|
|
var globalDiskCache = NewDiskSpaceCache(30 * time.Second)
|
|
|
|
// CheckDiskSpaceCached performs cached disk space check
|
|
func CheckDiskSpaceCached(path string) *DiskSpaceCheck {
|
|
return globalDiskCache.Get(path)
|
|
} |