Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116package engine
import ( "context" "log/slog" "time"
"tangled.org/core/spindle/db" "tangled.org/core/spindle/storage")
const ( cachePruneBatch = 100 cachePendingMaxAge = time.Hour)
func StartCachePruner(ctx context.Context, l *slog.Logger, index *db.DB, store storage.Storage, retention, interval time.Duration) { if store == nil || interval <= 0 { return } go func() { prune := func() { total := 0 for { n, err := PruneCaches(ctx, index, store, time.Now(), retention, cachePendingMaxAge, cachePruneBatch) total += n if err != nil { l.Warn("cache prune failed", "count", total, "err", err) return } if n < cachePruneBatch { if total > 0 { l.Info("pruned cache entries", "count", total) } return } } } prune() ticker := time.NewTicker(interval) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: prune() } } }()}
func PruneCaches(ctx context.Context, index *db.DB, store storage.Storage, now time.Time, retention, pendingMaxAge time.Duration, limit int) (int, error) { deletions, err := index.PendingCacheObjectDeletions(ctx, limit) if err != nil { return 0, err } pruned := 0 for _, key := range deletions { entries, err := index.CacheEntriesByStorageKey(ctx, key) if err != nil { return pruned, err } pinned := false for _, entry := range entries { if entry.RestoreCount > 0 { pinned = true break } } if pinned { continue } if err := store.Delete(ctx, key); err != nil { return pruned, err } if err := index.CompleteCacheObjectDeletion(ctx, key); err != nil { return pruned, err } if err := index.DeleteCacheEntriesByStorageKey(ctx, key); err != nil { return pruned, err } pruned++ } if pruned == limit { return pruned, nil }
readyBefore := time.Unix(0, 0) if retention > 0 { readyBefore = now.Add(-retention) } entries, err := index.ExpiredCacheEntries(ctx, readyBefore, now.Add(-pendingMaxAge), limit-pruned) if err != nil { return pruned, err } for _, entry := range entries { claimed, err := index.ClaimCacheEntry(ctx, entry.ID, entry.State, entry.LastUsedAt) if err != nil { return pruned, err } if !claimed { continue } if err := store.Delete(ctx, entry.StorageKey); err != nil { _ = index.RestoreCacheEntryState(context.WithoutCancel(ctx), entry.ID, entry.State) return pruned, err } if err := index.DeleteCacheEntry(ctx, entry.ID); err != nil { return pruned, err } pruned++ } return pruned, nil}