Files
WRNexusJS/packages/cache
ClintchizandClaude Opus 5 1fb1a8d2d0
Quality / quality (ubuntu-latest) (push) Failing after 12m21s
Quality / quality (windows-latest) (push) Canceled after 0s
chore(release): prepare 0.8.5
Bumps every @wrnexus package 0.8.4 -> 0.8.5 and adds the matching update
migration. The migration is documentation only: moving off <Table> to
<DataTable> and off the @wrnexus/ui main entry to @wrnexus/ui/registry are
source changes no codemod can make safely.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 15:08:05 +05:30
..
2026-08-02 23:18:51 +05:30
2026-08-02 23:18:51 +05:30
2026-08-07 15:08:05 +05:30
2026-08-02 23:18:51 +05:30

@wrnexus/cache

Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation.

import { connectCacheInvalidation, TagCache, responseCache } from "@wrnexus/cache";
const cache = new TagCache({ ttlMs: 60_000, staleWhileRevalidateMs: 300_000 });
export default responseCache({ cache, tags: ["products"] });

TagCache bounds entries with LRU-style eviction, deduplicates concurrent loaders, and prevents an invalidated in-flight loader from repopulating stale data. Use lookup() when fresh/stale state matters, or getOrLoad() for stampede-safe loading.

For multi-instance applications, connect the cache to any compatible pub/sub bus (including @wrnexus/pubsub). Namespaces isolate applications sharing the same broker. Local invalidation happens first and the returned promise confirms cross-instance publication; failures remain visible to the caller.

import { connectCacheInvalidation, TagCache } from "@wrnexus/cache";
import { createPubSub } from "@wrnexus/pubsub";
import { redisDriver } from "@wrnexus/pubsub/redis";

const cache = new TagCache({ maxEntries: 10_000 });
const bus = createPubSub(redisDriver(process.env.REDIS_URL));
const invalidation = connectCacheInvalidation(cache, bus, {
  namespace: "storefront-production",
  onError: (error) => logger.error("cache invalidation failed", { error }),
});

await invalidation.invalidateTag("products");
await invalidation.delete("product:42");

// Unsubscribes this cache only; the shared bus remains owned by the app.
invalidation.close();
await bus.close();

Framework cache layers

CacheCoordinator keeps the four cache lifetimes explicit:

  • coordinator.request() creates request-only deduplication.
  • coordinator.data caches loader/query results.
  • coordinator.component caches reusable rendered fragments.
  • coordinator.page caches complete safe documents.

All cross-request layers are bounded, tag-aware, stale-while-revalidate capable, stampede-safe, and expose withLock() for exclusive per-key work. inspect() returns metadata without cached values. Development applications expose that inspection through the Cache panel and GET /__wrnexus/cache.

Pages and components can opt in declaratively:

cache {
  scope = "page"
  strategy = "stale-while-revalidate"
  ttl = "5m"
  stale = "10m"
  tags = ["catalog", "marketing"]
  vary = ["tenant", "language"]
}

Omit scope to cache named loader data. Use scope = "page" for full-page caching. Component policies cache their rendered fragment. Authenticated user and tenant identities are always included automatically; page caches also vary by language, theme, and accent. Add header names or cookie:name entries for other application-specific variation. Pages containing CSRF forms are never stored in the full-page cache.