@plinthjs/cache
v0.1.0
Published
Mason cache: store contract, in-memory store, atomic locks, remember (the Illuminate\Cache equivalent).
Maintainers
Readme
@plinthjs/cache
The Mason cache layer — the Illuminate\Cache equivalent. A swappable store contract, an
in-memory store, the user-facing repository (with remember), and atomic locks.
Everything that observes time takes an injected now clock (epoch milliseconds), so expiry and
lock timeouts are deterministic. The default reads the system clock.
Usage
import { arrayCache } from '@plinthjs/cache'
const cache = arrayCache()
await cache.put('answer', 42, 60) // store for 60 seconds
await cache.get('answer') // 42
await cache.has('answer') // true
// Compute-once-then-cache. The callback runs only on a miss (and again after expiry).
const user = await cache.remember('user:1', 300, async () => fetchUser(1))
const config = await cache.rememberForever('config', loadConfig)
// Fetch-and-remove.
const flash = await cache.pull('flash')
// Atomic counters.
await cache.increment('hits') // 1
await cache.decrement('hits') // 0Building blocks
import { ArrayStore, Repository } from '@plinthjs/cache'
const store = new ArrayStore() // implements the Store contract
const cache = new Repository(store)Locks
const lock = cache.lock('reports', 10) // auto-expire after 10s
// Run a critical section only if the lock is free; always released afterwards.
const result = await lock.get(async () => generateReport())
if (result === false) {
// someone else holds the lock
}
// Block until the lock is free, or throw LockTimeoutError after 5 seconds.
await lock.block(5, async () => generateReport())Deterministic tests
Inject a fake clock so expiry never depends on the wall clock:
let now = 0
const cache = arrayCache({ now: () => now })
await cache.put('k', 1, 60) // expires at now + 60_000 ms
now = 60_001
await cache.get('k') // null — expired