Files
WRNexusJS/packages/cache
ClintchizandClaude Opus 5 7a2b58652a
Quality / quality (ubuntu-latest) (push) Failing after 11m2s
Quality / quality (windows-latest) (push) Canceled after 0s
chore(release): prepare 0.8.6
Bumps all 47 packages, the root manifest and the VS Code extension to 0.8.6,
and rebuilds the editor compiler, language server and extension bundles that
embed the version.

The release carries the output delivery fix: camelCase outputs now reach
parent bindings, and 18 components emit through output.* instead of
hand-built CustomEvents. See the 0.8.6 migration entry for what changes for
consumers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:54:44 +05:30
..
2026-08-02 23:18:51 +05:30
2026-08-02 23:18:51 +05:30
2026-08-09 01:54:44 +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.