Skip to main content

stacks-cache

Use when implementing caching in Stacks - memory cache, Redis cache, cache-aside pattern (getOrSet), TTL management, cache stats, or cache configuration. Covers @stacksjs/cache and config/cache.ts.

Source facts

Repository
stacksjs/wildloop
Last source activity
October 22, 2026 at 16:48
Detected SKILL.md language
English
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
stacks-cache
description
Use when implementing caching in Stacks - memory cache, Redis cache, cache-aside pattern (getOrSet), TTL management, cache stats, or cache configuration. Covers @stacksjs/cache and config/cache.ts.
license
MIT
compatibility
Bun >= 1.3.0, TypeScript
allowed-tools
Read Edit Write Bash Grep Glob
# Stacks Cache Use `@stacksjs/cache` for cache-aside reads, explicit TTLs and invalidation. Read `config/cache.ts` and the selected factory before assuming shared state. ## API and TTL ~~~ts import { cache } from '@stacksjs/cache' await cache.set('product:42', { name: 'Widget' }, 60) const product = await cache.get<{ name: string }>('product:42') const products = await cache.mget<{ name: string }>(['product:42', 'product:43']) // mget returns a record keyed by cache key, not an array. ~~~ - TTL is in seconds. Zero means forever; omitted TTL uses the factory's stdTTL, which defaults to zero. The exported cache/memory singleton is a memory instance with no default expiry. Config's ttl value does not silently turn that singleton into a configured Redis instance. - `setForever` stores without expiry; `getTtl` reads remaining TTL and `ttl(key, seconds)` updates it. Missing values are undefined. - `mset([{ key, value, ttl? }])` writes entries. `del(keyOrKeys)` and `deleteMany(keys)` return counts; `remove(key)` returns void. - `has/missing/take`, `keys(pattern?)`, `getStats`, `clear/flush` and `close/disconnect` provide the remaining facade API. Consult the driver before relying on take for a distributed atomic claim. ## Cache-aside and concurrent misses `getOrSet(key, fetcher, ttl?)` computes and stores only on a miss. `remember(key, ttl, callback)` is its Laravel-style argument order; `rememberForever(key, callback)` uses TTL zero. Concurrent misses share a promise within one StacksCache instance. Its bounded inflight timeout rejects every joined caller and frees that slot for retry. The underlying fetcher continues running after timeout; this is not cancellation or a lock shared across worker processes. For a distributed lock, inspect the re-exported CacheLock contract and selected driver separately. ## Drivers `createMemoryCache(options?)` accepts stdTTL, checkPeriod, maxKeys, useClones and prefix. Clone-on-read/write is enabled by default. `createRedisCache(options?)` accepts URL or host/port/credentials/database/TLS plus TTL/prefix options. `createSingleStoreCache(options?)` exposes the experimental SQL-backed cache. `createSqliteCache(options?)` keeps entries in a table of a SQLite file (`path`, `table`, `prefix`, `stdTTL`), so they outlive the process: use it for results that are expensive and safe to keep across deploys, pointing `path` at a file the deploy preserves (the app's own SQLite database works; the table is the driver's alone). `createCache(driver, options?)` selects one of memory, redis, singlestore or sqlite. The `cache` export is the driver `config/cache.ts` selects (`driver`, with `prefix` and `ttl` applied to the non-memory drivers), resolved on first use and once the app's config has loaded. With the default `driver: 'memory'` it answers from the `memory` instance itself. `cacheFromConfig(settings?)` builds the same choice explicitly; `resetConfiguredCache()` forgets it. The capability registry proves memory and a versioned Redis core/TTL contract; TLS/authenticated Redis deployments need separate provider evidence. SingleStore has no dedicated service conformance matrix. Source: `storage/framework/core/config/src/capabilities.ts`. ## Tag invalidation and advanced patterns `StacksCache.tags(['products', 'tenant-7'])` creates a TaggedCache supporting put/set/setForever, remember/rememberForever, get/has and flush. Its tag index uses the same backend; process persistence depends on that backend. Tags label shared keys rather than granting tenant authorization. Construct an explicit tenant key/prefix as well when isolation matters. The package also re-exports CacheAsidePattern, MultiLevelPattern, RefreshAheadPattern, WriteThroughPattern, BatchOperations, CacheInvalidation, CacheLock, CircuitBreaker, memoize and RateLimiter from ts-cache. Read the installed upstream types before using these advanced classes; their signatures are distinct from StacksCache and auth's RateLimiter. ## Source and verification `storage/framework/core/cache/src/drivers/index.ts` is the facade/factory contract. `drivers/singlestore.ts` owns the experimental backend and `drivers/sqlite.ts` the durable file-backed one (`sqlite-cache.test.ts`). Retained tests: `ttl.test.ts`, `getorset-timeout.test.ts`, `tagged-flush-race.test.ts`, `redis-contract.test.ts` and `cache-factory.test.ts` under `core/cache/tests/`. ## Representation-aware keys `cacheKey(namespace, dependencies)` creates a deterministic key from named primitive dependencies. Include owner/tenant scope, content version and every setting affecting the result (for example privacy, locale or theme). Property order does not change it; delimiter-containing strings cannot collide. Null and undefined remain distinct. This constructs identity; it does not observe settings, grant authorization or invalidate already issued public URLs. The narrow `@stacksjs/cache/key` entry is pure and browser-bundleable.
View on GitHub