feat: DB-tracked cache size accounting with background LRU eviction
Migration 002 adds a variant_content table (processed variants were untracked on disk) and an LRU timestamp on source_content. Total usage is two SUMs, never a directory scan on the hot path; hits touch LRU timestamps best-effort. A background goroutine evicts globally least-recently-used entries (variants and source blobs merged) until usage is under MaxBytes, woken by a periodic ticker and by non-blocking write-pressure notifications from stores. Evicting a source blob deletes all source_metadata rows referencing it plus its source_content row in one transaction before the file is unlinked, so multi-referenced blobs are removed only with all their references and rows never point at deleted files; JSON sidecars are cleaned up too. A one-time startup reconciliation walk adopts untracked variant files, drops rows whose files are missing, removes unreachable source blobs, and sweeps stale temp files. CacheConfig.DisableDiskCache turns the disk cache off entirely (config maps cache_max_bytes: 0 to it): no directories, lookups miss, stores no-op, no evictor. Handlers wire the limit, start eviction on startup, and stop it on shutdown.
This commit is contained in:
@@ -493,6 +493,24 @@ func (s *VariantStorage) Delete(key VariantKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteWithMeta removes the content at the given key together with
|
||||
// its .meta sidecar file. A missing file is not an error.
|
||||
func (s *VariantStorage) DeleteWithMeta(key VariantKey) error {
|
||||
if err := s.Delete(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metaPath := s.keyToPath(key) + ".meta"
|
||||
|
||||
//nolint:gosec // G703: path derived from cache key
|
||||
err := os.Remove(metaPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to delete variant metadata: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// keyToPath converts a key to a file path: <basedir>/<ab>/<cd>/<key>
|
||||
func (s *VariantStorage) keyToPath(key VariantKey) string {
|
||||
k := string(key)
|
||||
|
||||
Reference in New Issue
Block a user