⚙️ Aeon::CacheManager – 4 + 1 Architecture¶
Keeps time’s memory close, coherent, and fast.
1️⃣ Logical View¶
Purpose:
Aeon::CacheManager is Aeon’s unified caching interface.
It reads and writes serialized occurrences to Redis, with optional in-process memoization.
Responsibilities
- fetch → read or compute and store.
- write / delete / clear_expired.
- Enforce TTL and size limits.
- Support tag-based invalidation (topic: prefix).
2️⃣ Process View¶
- Timekeeper requests occurrences for a period.
- CacheManager computes key via
CacheWindow.key_for. - If found → deserialize and return.
- If missing → execute block, store serialized JSON, set TTL.
- Refresher periodically rehydrates near-expiring keys.
3️⃣ Development View¶
File: app/services/aeon/cache_manager.rb
class Aeon::CacheManager
TTL_DEFAULT = 6.hours
def self.fetch(key, ttl: TTL_DEFAULT)
cached = Redis.current.get(key)
return deserialize(cached) if cached
value = yield
Redis.current.set(key, serialize(value), ex: ttl.to_i)
value
end
def self.delete(key) = Redis.current.del(key)
def self.clear_expired; end # handled by Redis TTL
def self.serialize(v) = JSON.dump(v)
def self.deserialize(v) = JSON.parse(v, symbolize_names: true)
end
4️⃣ Physical View¶
| Attribute | Description |
|---|---|
| Store | Redis 6+ |
| TTL | Configurable (6 h default) |
| Index | key prefix aeon:cache: |
| Observability | Argus metrics aeon_cache_hits_total |
➕ 1 Scenario View¶
Scenario A: Cache Hit¶
CacheManager.fetch("aeon:cache:task:abc") { slow_query }
# => returns cached payload
Scenario B: Cache Miss¶
Computes from source and stores new entry.
Scenario C: Expiry¶
After TTL passes, Refresher detects and rebuilds.