@warlock.js/cache 5.34.1 → 5.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/llms-full.txt +50 -73
- package/llms.txt +1 -1
- package/package.json +3 -3
- package/skills/index.md +25 -2
- package/skills/overview/SKILL.md +0 -69
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to `@warlock.js/cache` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.34.2 - 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Merge package orientation into the grouped skill index and remove the duplicate overview topic; preserve that orientation in generated LLM projections. List the cache utility topic in the index and fix the orientation link.
|
|
12
|
+
|
|
7
13
|
## 5.32.0 - 2026-10-18
|
|
8
14
|
|
|
9
15
|
### Changed
|
package/llms-full.txt
CHANGED
|
@@ -4,6 +4,56 @@
|
|
|
4
4
|
|
|
5
5
|
> Generated artifact. Concatenates every SKILL.md and reference file under `@warlock.js/cache/skills/`. Re-run `node scripts/generate-llms.mjs` after any change.
|
|
6
6
|
|
|
7
|
+
## Package orientation
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
description: 'Cache layer for Warlock apps with pluggable drivers (memory, LRU, file, Redis, Postgres). Exports `cache`, `CacheManager`, `cached`, `TaggedCache`, `ScopedCache`, `RedisCacheDriver`, `MemoryCacheDriver`, `MockCacheDriver`, `PgCacheDriver`. Use for: "cache this query for 5 minutes", "invalidate every key for tenant 42", "stale-while-revalidate", "take a lock so only one worker runs this", "tag keys and flush the tag", "increment a counter in cache". Not this package: HTTP response/page caching belongs to @warlock.js/core or web; persistent data is a @warlock.js/cascade model.'
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# @warlock.js/cache
|
|
14
|
+
|
|
15
|
+
The `cache` singleton (a `CacheManager`) fronts one active driver. Everything, from `get`/`set` through `remember`, `swr`, `tags`, `namespace`, `lock` and `list`, works the same on any driver, so pick a driver once and write app code against `cache`.
|
|
16
|
+
|
|
17
|
+
## The 80% path
|
|
18
|
+
|
|
19
|
+
1. Start with `cache-basics.md`.
|
|
20
|
+
2. Choose and configure a driver: `pick-cache-driver.md` (Postgres: `configure-pg-cache.md`; TTL and options: `configure-set-options.md`).
|
|
21
|
+
3. Cache expensive reads with `remember` or the `cached` wrapper: `use-cached-hof.md`, `apply-cache-patterns.md`.
|
|
22
|
+
4. Invalidate in groups: `use-cache-tags.md` or `use-cache-namespace.md`.
|
|
23
|
+
5. Stampede protection and freshness: `use-swr.md`, `use-cache-lock.md`.
|
|
24
|
+
6. TTL constants, key parsing and vector helpers: `use-cache-utils.md`.
|
|
25
|
+
7. Test with the mock driver: `test-cache-code.md`; errors and metrics: `handle-cache-errors.md`, `observe-cache.md`.
|
|
26
|
+
|
|
27
|
+
## Conventions and pitfalls
|
|
28
|
+
|
|
29
|
+
- Tags versus namespaces: tags are cross-cutting groups you flush together; a namespace is a key prefix you remove wholesale. Choose per invalidation need.
|
|
30
|
+
- Check `configure-set-options.md` for TTL units, and avoid `forever` for data that can go stale.
|
|
31
|
+
- Atomic counters, bulk ops, lists, merge and similarity have their own topics (`use-cache-atomic.md`, `use-cache-bulk.md`, `use-cache-list.md`, `use-cache-update-merge.md`, `use-cache-similarity.md`); do not hand-roll read-modify-write.
|
|
32
|
+
- Not every driver supports every feature; check the driver topic first.
|
|
33
|
+
|
|
34
|
+
## When to reach for it
|
|
35
|
+
|
|
36
|
+
- You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
|
|
37
|
+
- You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
|
|
38
|
+
- You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
|
|
39
|
+
|
|
40
|
+
Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
|
|
41
|
+
|
|
42
|
+
## The mental model in one paragraph
|
|
43
|
+
|
|
44
|
+
A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
|
|
45
|
+
|
|
46
|
+
## What this package deliberately doesn't do
|
|
47
|
+
|
|
48
|
+
- **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
|
|
49
|
+
- **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
|
|
50
|
+
- **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
|
|
51
|
+
|
|
52
|
+
## See also
|
|
53
|
+
|
|
54
|
+
- The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
|
|
55
|
+
|
|
56
|
+
|
|
7
57
|
## apply-cache-patterns `@warlock.js/cache/apply-cache-patterns/SKILL.md`
|
|
8
58
|
|
|
9
59
|
---
|
|
@@ -668,79 +718,6 @@ Drivers that never fire events stay absent from `byDriver` — guard with `?.` a
|
|
|
668
718
|
- Don't forget to attach early. If startup metrics matter, call `cache.metrics()` right after `cache.init()`.
|
|
669
719
|
|
|
670
720
|
|
|
671
|
-
## overview `@warlock.js/cache/overview/SKILL.md`
|
|
672
|
-
|
|
673
|
-
---
|
|
674
|
-
name: overview
|
|
675
|
-
description: "@warlock.js/cache overview for orientation and choosing the focused skill for the task."
|
|
676
|
-
---
|
|
677
|
-
|
|
678
|
-
# `@warlock.js/cache` — overview
|
|
679
|
-
|
|
680
|
-
One cache API over many drivers. Pick a driver (memory, memoryExtended, LRU, file, Redis, Postgres, null, mock), wire it once, and call `cache.get` / `cache.set` / `cache.remember` everywhere. On top of the key-value basics it adds tag invalidation, key namespaces, distributed locks, stale-while-revalidate, atomic update/merge, ordered lists, vector similarity, and built-in metrics + events.
|
|
681
|
-
|
|
682
|
-
## When to reach for it
|
|
683
|
-
|
|
684
|
-
- You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
|
|
685
|
-
- You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
|
|
686
|
-
- You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
|
|
687
|
-
|
|
688
|
-
Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
|
|
689
|
-
|
|
690
|
-
## The mental model in one paragraph
|
|
691
|
-
|
|
692
|
-
A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
|
|
693
|
-
|
|
694
|
-
## Skills index
|
|
695
|
-
|
|
696
|
-
Nineteen task skills. Most apps start with `cache-basics` + `pick-cache-driver` + `configure-set-options`.
|
|
697
|
-
|
|
698
|
-
### Foundations
|
|
699
|
-
|
|
700
|
-
- The `cache-basics` topic — the `cache` singleton, primary ops (`set`/`get`/`has`/`pull`/`remove`/`many`/`forever`/`increment`/`decrement`/`remember`), TTL shapes, init flow. **Start here.**
|
|
701
|
-
- The `pick-cache-driver` topic — choose + configure a driver: `null` / `memory` / `memoryExtended` / `lru` / `file` / `redis` / `pg` / `mock`; `globalPrefix` for multi-tenant scoping.
|
|
702
|
-
- The `configure-set-options` topic — `cache.set`'s third argument: `ttl`, `expiresAt`, `tags`, `onConflict` (create/update/upsert), `driver`, `vector`.
|
|
703
|
-
- The `configure-pg-cache` topic — Postgres driver: KV-only (default) or pgvector mode; caller owns the `pg.Pool`, `driver.schema()` emits the DDL.
|
|
704
|
-
|
|
705
|
-
### Invalidation + scoping
|
|
706
|
-
|
|
707
|
-
- The `use-cache-tags` topic — tag on write, `cache.tags([...]).invalidate()` drops every bound key.
|
|
708
|
-
- The `use-cache-namespace` topic — `cache.namespace(prefix, options?)` auto-prefixes keys with scope-level TTL/tag defaults and nested scopes.
|
|
709
|
-
|
|
710
|
-
### Patterns
|
|
711
|
-
|
|
712
|
-
- The `use-cached-hof` topic — `cached(fn, options)` wraps an async function; one declaration, many call sites, a bound `.invalidate(...args)`.
|
|
713
|
-
- The `apply-cache-patterns` topic — `remember()` memoization, distributed locks via `onConflict: "create"`, negative caching, counters, per-tenant prefix, `CACHE_FOR.*` TTL constants.
|
|
714
|
-
- The `use-cache-lock` topic — `cache.lock(key, ttl, fn)`: acquire → run → auto-release. For cron/imports/migrations and idempotent webhook/payment processing.
|
|
715
|
-
- The `use-swr` topic — `cache.swr(key, { freshTtl, staleTtl }, fn)`: instant when fresh, instant + background refresh when stale, blocks only when fully expired.
|
|
716
|
-
- The `use-cache-update-merge` topic — atomic read-modify-write via `cache.update(key, fn)` / `cache.merge(key, partial)`, serialized per key, TTL-preserving.
|
|
717
|
-
- The `use-cache-atomic` topic — `cache.increment` / `cache.decrement` counters; per-driver atomicity + TTL behavior.
|
|
718
|
-
- The `use-cache-bulk` topic — `cache.many(keys)` / `cache.setMany(record, ttl?)` for batch reads/writes.
|
|
719
|
-
- The `use-cache-list` topic — `cache.list<T>(key)`: `push`/`unshift`/`pop`/`shift`/`slice`/`trim`/`clear` for queues, recent-N buffers, sliding windows.
|
|
720
|
-
- The `use-cache-similarity` topic — `cache.similar(vector, { topK, threshold?, tags? })` for semantic caches, RAG retrieval, nearest-neighbor lookup.
|
|
721
|
-
|
|
722
|
-
### Operations
|
|
723
|
-
|
|
724
|
-
- The `observe-cache` topic — `cache.metrics()` (hit rate, latency p50/p95/p99) + the event bus (`cache.on("hit" | "miss" | "set" | "removed" | "flushed" | "expired" | "connected" | "disconnected" | "error", …)`).
|
|
725
|
-
- The `handle-cache-errors` topic — the error classes: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`.
|
|
726
|
-
- The `test-cache-code` topic — `MockCacheDriver` (behavioral assertions), `MemoryCacheDriver` (full-stack), `NullCacheDriver` (graceful degradation).
|
|
727
|
-
|
|
728
|
-
### Utilities
|
|
729
|
-
|
|
730
|
-
- The `use-cache-utils` topic — low-level re-exports: `parseTtl`, `parseCacheKey`, `resolveTtl`, `expiresAtToTtl`, `mergeTagSets`, `injectTags`, `cosineSimilarity`, and the `CACHE_FOR` TTL enum.
|
|
731
|
-
|
|
732
|
-
## What this package deliberately doesn't do
|
|
733
|
-
|
|
734
|
-
- **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
|
|
735
|
-
- **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
|
|
736
|
-
- **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
|
|
737
|
-
|
|
738
|
-
## See also
|
|
739
|
-
|
|
740
|
-
- The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
|
|
741
|
-
- `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this becomes `.claude/skills/warlock-js-cache/overview.md`.
|
|
742
|
-
|
|
743
|
-
|
|
744
721
|
## pick-cache-driver `@warlock.js/cache/pick-cache-driver/SKILL.md`
|
|
745
722
|
|
|
746
723
|
---
|
package/llms.txt
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
## Skills
|
|
8
8
|
|
|
9
|
+
- [Package orientation](@warlock.js/cache/skills/index.md): Cache layer for Warlock apps with pluggable drivers (memory, LRU, file, Redis, Postgres). Exports `cache`, `CacheManager`, `cached`, `TaggedCache`, `ScopedCache`, `RedisCacheDriver`, `MemoryCacheDriver`, `MockCacheDriver`, `PgCacheDriver`. Use for: "cache this query for 5 minutes", "invalidate every key for tenant 42", "stale-while-revalidate", "take a lock so only one worker runs this", "tag keys and flush the tag", "increment a counter in cache". Not this package: HTTP response/page caching belongs to @warlock.js/core or web; persistent data is a @warlock.js/cascade model.
|
|
9
10
|
- [apply-cache-patterns](@warlock.js/cache/apply-cache-patterns/SKILL.md): Compose cache primitives into real-world patterns — remember() memoization, cross-node stampede protection via a distributed lock (onConflict: 'create'), negative caching, and per-tenant scoping. Triggers: `cache.remember`, `cache.set` with `onConflict: "create"`, `globalPrefix`; "memoize this function", "prevent cache stampede across nodes", "cache not-found results", "per-tenant cache scoping"; typical import `import { cache } from "@warlock.js/cache"`. Skip: counters — the `use-cache-atomic` topic; bulk get/set — the `use-cache-bulk` topic; TTL constants/utilities — the `use-cache-utils` topic; named lock wrapper — the `use-cache-lock` topic; SWR — the `use-swr` topic; competing libs `lru-cache`, `node-cache`, `keyv`.
|
|
10
11
|
- [cache-basics](@warlock.js/cache/cache-basics/SKILL.md): Start here for @warlock.js/cache drivers, key-value operations, and application cache configuration.
|
|
11
12
|
- [configure-pg-cache](@warlock.js/cache/configure-pg-cache/SKILL.md): Postgres cache driver setup — KV-only mode (default) or pgvector mode (opt in via options.pg.vector). Caller owns the pg.Pool, driver exposes driver.schema() for one-time DDL. Triggers: `PgCacheDriver`, `driver.schema`, `options.pg.vector`, `pg.Pool`, `hnsw`, `ivfflat`; "use Postgres as cache backend", "set up pgvector semantic cache", "DDL for warlock cache table"; typical import `import { cache, PgCacheDriver } from "@warlock.js/cache"`. Skip: cross-driver similarity API — the `use-cache-similarity` topic; driver picker — the `pick-cache-driver` topic; competing libs `pg-mem`; raw `pg` / `node-postgres`.
|
|
12
13
|
- [configure-set-options](@warlock.js/cache/configure-set-options/SKILL.md): Configure cache.set's third argument — ttl, expiresAt, tags, onConflict (create / update / upsert), driver, vector. Triggers: `cache.set`, `ttl`, `expiresAt`, `tags`, `onConflict`, `driver`, `vector`, `CacheSetResult`, `wasSet`; "set a key only if missing", "set with absolute deadline", "attach tags inline", "route one cache call to redis"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag fluent API — the `use-cache-tags` topic; vector queries — the `use-cache-similarity` topic; competing libs `keyv`, `ioredis`.
|
|
13
14
|
- [handle-cache-errors](@warlock.js/cache/handle-cache-errors/SKILL.md): Cache error classes — CacheError base, CacheConfigurationError, CacheConnectionError, CacheDriverNotInitializedError, CacheUnsupportedError, CacheConcurrencyError. Triggers: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`; "catch cache errors at the boundary", "degrade when update or merge throws", "what does CacheUnsupportedError mean", "fall back when redis is down"; typical import `import { CacheError, CacheConfigurationError, CacheUnsupportedError } from "@warlock.js/cache"`. Skip: choosing a supported driver — the `pick-cache-driver` topic; observing errors via events — the `observe-cache` topic; competing libs ignore — generic `Error` patterns.
|
|
14
15
|
- [observe-cache](@warlock.js/cache/observe-cache/SKILL.md): Cache observability — cache.metrics() for aggregate hit rate / latency p50/p95/p99 + event bus (cache.on('hit' / 'miss' / 'set' / 'removed' / 'flushed' / 'expired' / 'error', ...)). Triggers: `cache.metrics`, `cache.resetMetrics`, `cache.on`, `hit`, `miss`, `removed`, `flushed`, `error`, `hitRate`, `latencyMs`; "show cache hit rate", "page on cache errors", "is my cache being hit", "export metrics to prometheus"; typical import `import { cache } from "@warlock.js/cache"`. Skip: error classes — the `handle-cache-errors` topic; competing libs `prom-client`, `statsd-client`.
|
|
15
|
-
- [overview](@warlock.js/cache/overview/SKILL.md): @warlock.js/cache overview for orientation and choosing the focused skill for the task.
|
|
16
16
|
- [pick-cache-driver](@warlock.js/cache/pick-cache-driver/SKILL.md): Pick a cache driver — null / memory / memoryExtended / lru / file / redis / pg / mock — and configure it. Triggers: `cache.setCacheConfigurations`, `BaseCacheDriver`, `cache.use`, `cache.load`, `cache.driver`, `globalPrefix`; "which cache driver should I use", "configure redis driver", "register custom cache driver", "multi-tenant scoping"; typical import `import { cache, BaseCacheDriver } from "@warlock.js/cache"`. Skip: cache CRUD — the `cache-basics` topic; pg setup — the `configure-pg-cache` topic; competing libs `lru-cache`, `node-cache`, `keyv`, `ioredis`; native `Map`.
|
|
17
17
|
- [test-cache-code](@warlock.js/cache/test-cache-code/SKILL.md): Test code that touches cache — MockCacheDriver (behavioral assertions with wasCalled / callLog), MemoryCacheDriver (full-stack), NullCacheDriver (graceful-degradation). Triggers: `MockCacheDriver`, `MemoryCacheDriver`, `NullCacheDriver`, `wasCalled`, `callLog`, `getStored`, `reset`, `cache.on`; "assert cache was invalidated", "test code that uses cache.set", "mock cache in vitest", "test similarity without a real embedder", "stub the pg cache driver"; typical import `import { cache, MockCacheDriver, MemoryCacheDriver } from "@warlock.js/cache"`. Skip: real driver picks — the `pick-cache-driver` topic; competing libs `jest-mock`, `sinon`, `redis-mock`; native `vi.fn`.
|
|
18
18
|
- [use-cache-atomic](@warlock.js/cache/use-cache-atomic/SKILL.md): Atomic counters via cache.increment(key, by=1, { ttl }?) / cache.decrement(key, by=1) — returns the new number, throws on non-numeric values. Triggers: `cache.increment`, `cache.decrement`, "view counter", "page views", "atomic counter", "decrement stock", "rate-limit counter", "INCRBY"; typical import `import { cache } from "@warlock.js/cache"`. Skip: read-modify-write of objects — the `use-cache-update-merge` topic; named-lock coordination — the `use-cache-lock` topic; competing libs `ioredis` `INCR`, native counters in a `Map`.
|
package/package.json
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"environment": "server"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@warlock.js/fs": "5.34.
|
|
8
|
+
"@warlock.js/fs": "5.34.2",
|
|
9
9
|
"@mongez/reinforcements": "^4.0.2",
|
|
10
|
-
"@warlock.js/logger": "5.34.
|
|
10
|
+
"@warlock.js/logger": "5.34.2",
|
|
11
11
|
"ms": "^2.1.3"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
],
|
|
48
48
|
"author": "hassanzohdy",
|
|
49
49
|
"license": "MIT",
|
|
50
|
-
"version": "5.34.
|
|
50
|
+
"version": "5.34.2",
|
|
51
51
|
"main": "./cjs/index.cjs",
|
|
52
52
|
"module": "./esm/index.mjs",
|
|
53
53
|
"types": "./esm/index.d.mts",
|
package/skills/index.md
CHANGED
|
@@ -8,12 +8,13 @@ The `cache` singleton (a `CacheManager`) fronts one active driver. Everything, f
|
|
|
8
8
|
|
|
9
9
|
## The 80% path
|
|
10
10
|
|
|
11
|
-
1.
|
|
11
|
+
1. Start with `cache-basics.md`.
|
|
12
12
|
2. Choose and configure a driver: `pick-cache-driver.md` (Postgres: `configure-pg-cache.md`; TTL and options: `configure-set-options.md`).
|
|
13
13
|
3. Cache expensive reads with `remember` or the `cached` wrapper: `use-cached-hof.md`, `apply-cache-patterns.md`.
|
|
14
14
|
4. Invalidate in groups: `use-cache-tags.md` or `use-cache-namespace.md`.
|
|
15
15
|
5. Stampede protection and freshness: `use-swr.md`, `use-cache-lock.md`.
|
|
16
|
-
6.
|
|
16
|
+
6. TTL constants, key parsing and vector helpers: `use-cache-utils.md`.
|
|
17
|
+
7. Test with the mock driver: `test-cache-code.md`; errors and metrics: `handle-cache-errors.md`, `observe-cache.md`.
|
|
17
18
|
|
|
18
19
|
## Conventions and pitfalls
|
|
19
20
|
|
|
@@ -21,3 +22,25 @@ The `cache` singleton (a `CacheManager`) fronts one active driver. Everything, f
|
|
|
21
22
|
- Check `configure-set-options.md` for TTL units, and avoid `forever` for data that can go stale.
|
|
22
23
|
- Atomic counters, bulk ops, lists, merge and similarity have their own topics (`use-cache-atomic.md`, `use-cache-bulk.md`, `use-cache-list.md`, `use-cache-update-merge.md`, `use-cache-similarity.md`); do not hand-roll read-modify-write.
|
|
23
24
|
- Not every driver supports every feature; check the driver topic first.
|
|
25
|
+
|
|
26
|
+
## When to reach for it
|
|
27
|
+
|
|
28
|
+
- You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
|
|
29
|
+
- You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
|
|
30
|
+
- You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
|
|
31
|
+
|
|
32
|
+
Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
|
|
33
|
+
|
|
34
|
+
## The mental model in one paragraph
|
|
35
|
+
|
|
36
|
+
A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
|
|
37
|
+
|
|
38
|
+
## What this package deliberately doesn't do
|
|
39
|
+
|
|
40
|
+
- **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
|
|
41
|
+
- **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
|
|
42
|
+
- **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
|
|
43
|
+
|
|
44
|
+
## See also
|
|
45
|
+
|
|
46
|
+
- The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
|
package/skills/overview/SKILL.md
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: overview
|
|
3
|
-
description: "@warlock.js/cache overview for orientation and choosing the focused skill for the task."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# `@warlock.js/cache` — overview
|
|
7
|
-
|
|
8
|
-
One cache API over many drivers. Pick a driver (memory, memoryExtended, LRU, file, Redis, Postgres, null, mock), wire it once, and call `cache.get` / `cache.set` / `cache.remember` everywhere. On top of the key-value basics it adds tag invalidation, key namespaces, distributed locks, stale-while-revalidate, atomic update/merge, ordered lists, vector similarity, and built-in metrics + events.
|
|
9
|
-
|
|
10
|
-
## When to reach for it
|
|
11
|
-
|
|
12
|
-
- You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
|
|
13
|
-
- You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
|
|
14
|
-
- You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
|
|
15
|
-
|
|
16
|
-
Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
|
|
17
|
-
|
|
18
|
-
## The mental model in one paragraph
|
|
19
|
-
|
|
20
|
-
A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
|
|
21
|
-
|
|
22
|
-
## Skills index
|
|
23
|
-
|
|
24
|
-
Nineteen task skills. Most apps start with `cache-basics` + `pick-cache-driver` + `configure-set-options`.
|
|
25
|
-
|
|
26
|
-
### Foundations
|
|
27
|
-
|
|
28
|
-
- The `cache-basics` topic — the `cache` singleton, primary ops (`set`/`get`/`has`/`pull`/`remove`/`many`/`forever`/`increment`/`decrement`/`remember`), TTL shapes, init flow. **Start here.**
|
|
29
|
-
- The `pick-cache-driver` topic — choose + configure a driver: `null` / `memory` / `memoryExtended` / `lru` / `file` / `redis` / `pg` / `mock`; `globalPrefix` for multi-tenant scoping.
|
|
30
|
-
- The `configure-set-options` topic — `cache.set`'s third argument: `ttl`, `expiresAt`, `tags`, `onConflict` (create/update/upsert), `driver`, `vector`.
|
|
31
|
-
- The `configure-pg-cache` topic — Postgres driver: KV-only (default) or pgvector mode; caller owns the `pg.Pool`, `driver.schema()` emits the DDL.
|
|
32
|
-
|
|
33
|
-
### Invalidation + scoping
|
|
34
|
-
|
|
35
|
-
- The `use-cache-tags` topic — tag on write, `cache.tags([...]).invalidate()` drops every bound key.
|
|
36
|
-
- The `use-cache-namespace` topic — `cache.namespace(prefix, options?)` auto-prefixes keys with scope-level TTL/tag defaults and nested scopes.
|
|
37
|
-
|
|
38
|
-
### Patterns
|
|
39
|
-
|
|
40
|
-
- The `use-cached-hof` topic — `cached(fn, options)` wraps an async function; one declaration, many call sites, a bound `.invalidate(...args)`.
|
|
41
|
-
- The `apply-cache-patterns` topic — `remember()` memoization, distributed locks via `onConflict: "create"`, negative caching, counters, per-tenant prefix, `CACHE_FOR.*` TTL constants.
|
|
42
|
-
- The `use-cache-lock` topic — `cache.lock(key, ttl, fn)`: acquire → run → auto-release. For cron/imports/migrations and idempotent webhook/payment processing.
|
|
43
|
-
- The `use-swr` topic — `cache.swr(key, { freshTtl, staleTtl }, fn)`: instant when fresh, instant + background refresh when stale, blocks only when fully expired.
|
|
44
|
-
- The `use-cache-update-merge` topic — atomic read-modify-write via `cache.update(key, fn)` / `cache.merge(key, partial)`, serialized per key, TTL-preserving.
|
|
45
|
-
- The `use-cache-atomic` topic — `cache.increment` / `cache.decrement` counters; per-driver atomicity + TTL behavior.
|
|
46
|
-
- The `use-cache-bulk` topic — `cache.many(keys)` / `cache.setMany(record, ttl?)` for batch reads/writes.
|
|
47
|
-
- The `use-cache-list` topic — `cache.list<T>(key)`: `push`/`unshift`/`pop`/`shift`/`slice`/`trim`/`clear` for queues, recent-N buffers, sliding windows.
|
|
48
|
-
- The `use-cache-similarity` topic — `cache.similar(vector, { topK, threshold?, tags? })` for semantic caches, RAG retrieval, nearest-neighbor lookup.
|
|
49
|
-
|
|
50
|
-
### Operations
|
|
51
|
-
|
|
52
|
-
- The `observe-cache` topic — `cache.metrics()` (hit rate, latency p50/p95/p99) + the event bus (`cache.on("hit" | "miss" | "set" | "removed" | "flushed" | "expired" | "connected" | "disconnected" | "error", …)`).
|
|
53
|
-
- The `handle-cache-errors` topic — the error classes: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`.
|
|
54
|
-
- The `test-cache-code` topic — `MockCacheDriver` (behavioral assertions), `MemoryCacheDriver` (full-stack), `NullCacheDriver` (graceful degradation).
|
|
55
|
-
|
|
56
|
-
### Utilities
|
|
57
|
-
|
|
58
|
-
- The `use-cache-utils` topic — low-level re-exports: `parseTtl`, `parseCacheKey`, `resolveTtl`, `expiresAtToTtl`, `mergeTagSets`, `injectTags`, `cosineSimilarity`, and the `CACHE_FOR` TTL enum.
|
|
59
|
-
|
|
60
|
-
## What this package deliberately doesn't do
|
|
61
|
-
|
|
62
|
-
- **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
|
|
63
|
-
- **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
|
|
64
|
-
- **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
|
|
65
|
-
|
|
66
|
-
## See also
|
|
67
|
-
|
|
68
|
-
- The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
|
|
69
|
-
- `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this becomes `.claude/skills/warlock-js-cache/overview.md`.
|