|
| 1 | +# Cache Eviction |
| 2 | + |
| 3 | +Fabrik provides automatic cache eviction to prevent unbounded disk usage. When the cache exceeds the configured `max_size`, Fabrik automatically removes objects based on the configured eviction policy. |
| 4 | + |
| 5 | +## Configuration |
| 6 | + |
| 7 | +Configure eviction in your `fabrik.toml`: |
| 8 | + |
| 9 | +```toml |
| 10 | +[cache] |
| 11 | +dir = ".fabrik/cache" |
| 12 | +max_size = "5GB" # Maximum cache size |
| 13 | +eviction_policy = "lfu" # lru | lfu | ttl |
| 14 | +default_ttl = "7d" # Default time-to-live for TTL policy |
| 15 | +``` |
| 16 | + |
| 17 | +## Eviction Policies |
| 18 | + |
| 19 | +### LFU (Least Frequently Used) - Default |
| 20 | + |
| 21 | +The LFU policy evicts objects with the lowest access count first. This is the default policy because it tends to preserve frequently-accessed build artifacts. |
| 22 | + |
| 23 | +```toml |
| 24 | +[cache] |
| 25 | +eviction_policy = "lfu" |
| 26 | +``` |
| 27 | + |
| 28 | +**Best for:** |
| 29 | +- Build caches with stable dependency trees |
| 30 | +- Projects where common artifacts are accessed repeatedly |
| 31 | +- CI environments with shared caches |
| 32 | + |
| 33 | +### LRU (Least Recently Used) |
| 34 | + |
| 35 | +The LRU policy evicts objects that haven't been accessed for the longest time. |
| 36 | + |
| 37 | +```toml |
| 38 | +[cache] |
| 39 | +eviction_policy = "lru" |
| 40 | +``` |
| 41 | + |
| 42 | +**Best for:** |
| 43 | +- Development environments with rapidly changing dependencies |
| 44 | +- Projects with distinct build phases |
| 45 | +- When recent builds are more important than frequency |
| 46 | + |
| 47 | +### TTL (Time To Live) |
| 48 | + |
| 49 | +The TTL policy evicts objects older than the configured TTL. Objects are evicted based on creation time, not access time. |
| 50 | + |
| 51 | +```toml |
| 52 | +[cache] |
| 53 | +eviction_policy = "ttl" |
| 54 | +default_ttl = "7d" # Evict objects older than 7 days |
| 55 | +``` |
| 56 | + |
| 57 | +**Best for:** |
| 58 | +- Compliance requirements with data retention limits |
| 59 | +- Ensuring cache freshness |
| 60 | +- Periodic cache invalidation scenarios |
| 61 | + |
| 62 | +## How Eviction Works |
| 63 | + |
| 64 | +Eviction runs **asynchronously in a background task**, ensuring that `put()` operations are never blocked by eviction: |
| 65 | + |
| 66 | +1. **Background Task**: A dedicated tokio task periodically checks cache size (default: every 30 seconds) |
| 67 | +2. **Trigger**: When cache exceeds `max_size`, the background task evicts objects |
| 68 | +3. **Target**: Fabrik evicts until the cache is at 90% of `max_size` (configurable via `target_ratio`) |
| 69 | +4. **Selection**: Objects are selected based on the configured policy |
| 70 | +5. **Batch Processing**: Up to 1000 objects are evicted per run to avoid overwhelming the system |
| 71 | +6. **Non-blocking**: `put()` operations proceed immediately without waiting for eviction |
| 72 | + |
| 73 | +### Metadata Tracking |
| 74 | + |
| 75 | +Fabrik tracks the following metadata for each cached object: |
| 76 | +- **Size**: Object size in bytes |
| 77 | +- **Created At**: When the object was first cached |
| 78 | +- **Accessed At**: Last access timestamp (updated on get/exists) |
| 79 | +- **Access Count**: Number of times the object was accessed |
| 80 | + |
| 81 | +This metadata is stored efficiently in RocksDB secondary indexes for fast eviction candidate selection. |
| 82 | + |
| 83 | +## Size Format |
| 84 | + |
| 85 | +The `max_size` configuration accepts human-readable size strings: |
| 86 | + |
| 87 | +| Format | Example | Bytes | |
| 88 | +|--------|---------|-------| |
| 89 | +| Terabytes | `1TB` | 1,099,511,627,776 | |
| 90 | +| Gigabytes | `5GB` | 5,368,709,120 | |
| 91 | +| Megabytes | `500MB` | 524,288,000 | |
| 92 | +| Kilobytes | `512KB` | 524,288 | |
| 93 | +| Bytes | `1024` | 1,024 | |
| 94 | + |
| 95 | +## TTL Format |
| 96 | + |
| 97 | +The `default_ttl` configuration accepts duration strings: |
| 98 | + |
| 99 | +| Format | Example | Seconds | |
| 100 | +|--------|---------|---------| |
| 101 | +| Days | `7d` | 604,800 | |
| 102 | +| Hours | `24h` | 86,400 | |
| 103 | +| Minutes | `30m` | 1,800 | |
| 104 | +| Seconds | `3600s` or `3600` | 3,600 | |
| 105 | + |
| 106 | +## Monitoring Eviction |
| 107 | + |
| 108 | +Fabrik logs eviction activity at the INFO level: |
| 109 | + |
| 110 | +``` |
| 111 | +INFO [fabrik] Eviction manager initialized: policy=lfu, max_size=5120MB, target_ratio=0.9 |
| 112 | +INFO [fabrik] Eviction complete: evicted 42 objects (128 MB) in 25ms |
| 113 | +``` |
| 114 | + |
| 115 | +## Environment Variable Overrides |
| 116 | + |
| 117 | +You can override eviction settings via environment variables: |
| 118 | + |
| 119 | +```bash |
| 120 | +# Override max cache size |
| 121 | +export FABRIK_CONFIG_CACHE_MAX_SIZE=10GB |
| 122 | + |
| 123 | +# Override eviction policy |
| 124 | +export FABRIK_CONFIG_CACHE_EVICTION_POLICY=lru |
| 125 | + |
| 126 | +# Override default TTL |
| 127 | +export FABRIK_CONFIG_CACHE_DEFAULT_TTL=14d |
| 128 | +``` |
| 129 | + |
| 130 | +## C API Support |
| 131 | + |
| 132 | +The C API provides two initialization functions: |
| 133 | + |
| 134 | +```c |
| 135 | +// Basic initialization with default eviction (5GB, LFU, 7 days) |
| 136 | +FabrikCache* cache = fabrik_cache_init("/path/to/cache"); |
| 137 | + |
| 138 | +// Custom eviction settings |
| 139 | +FabrikCache* cache = fabrik_cache_init_with_eviction( |
| 140 | + "/path/to/cache", |
| 141 | + 10ULL * 1024 * 1024 * 1024, // 10GB max size |
| 142 | + 1, // 0=LRU, 1=LFU, 2=TTL |
| 143 | + 7 * 24 * 60 * 60 // 7 days TTL |
| 144 | +); |
| 145 | +``` |
| 146 | + |
| 147 | +## Best Practices |
| 148 | + |
| 149 | +1. **Set realistic limits**: Choose a `max_size` that fits your available disk space while leaving room for other applications |
| 150 | +2. **Choose the right policy**: LFU works best for most build caches, but LRU may be better for development |
| 151 | +3. **Monitor eviction**: Watch the logs to ensure eviction is working as expected and adjust settings if needed |
| 152 | +4. **Consider TTL for compliance**: Use TTL policy when you need predictable cache expiration |
| 153 | + |
| 154 | +> [!NOTE] |
| 155 | +> Eviction runs asynchronously in the background every 30 seconds. The cache may temporarily exceed `max_size` between eviction runs. |
| 156 | +
|
| 157 | +> [!WARNING] |
| 158 | +> Setting `max_size` too low may cause frequent eviction and reduce cache hit rates. Monitor your cache performance after changing eviction settings. |
0 commit comments