Skip to content

Add tag-based and action-driven invalidation for server cache() #242

@vivek7405

Description

@vivek7405

Problem

A cached read (cache(fn,{key:'posts'})) can only be invalidated by calling listPosts.invalidate() from the exact module that owns the wrapper, and even then only the no-args base key is cleared (arg-specific keys leak until TTL). An unrelated mutation (createComment) cannot invalidate a related read (postById) without importing every cached wrapper, and the RPC action dispatcher (actions.js) has no hook to evict server cache() entries on a successful mutation. cache-fn.js takes only {key,ttl} and the CacheStore interface has only get/set/delete/increment with no tag index.

Design / approach

Implement tags as a thin Set-of-keys index in the existing store: cache(fn,{key,tags}) appends the key to each tag's Set, and revalidateTag(tag) deletes that Set's keys. No new subsystem, just a secondary index over store.get/set/delete; revalidateTag/revalidatePath are plain server-importable functions an action calls.

Web-standards fit: A tag is just a Set of keys layered on the existing store API; the whole feature is a small index plus two functions, no cache engine.

Prior art: Next.js unstable_cache(fn,keys,{tags}) plus revalidateTag(tag) invoked inside a Server Action; Rails russian-doll touch:.

Acceptance criteria

  • cache(fn,{key,tags:['posts']}) records the entry under each tag in the store
  • revalidateTag('posts') invalidates every entry tagged 'posts' across all modules, including arg-specific keys
  • CacheStore gains a tag-aware delete (or tag index) implemented for memoryStore and redisStore
  • revalidateTag is callable from inside a .server.ts action and evicts the tagged reads after a mutation
  • Unit tests: two reads sharing a tag both evicted by one revalidateTag call (untagged read survives); an action calling revalidateTag recomputes the next read
  • agent-docs/built-ins.md documents tags, revalidateTag, and the mutation-to-read contract
  • Tests cover the new behaviour at the applicable layer(s)
  • Docs / AGENTS.md / CONVENTIONS.md updated if the public surface changed

Filed from the production-readiness audit (webjs vs Next.js / Remix / Rails / Turbo / Lit). Theme: caching. Priority: P1. Kept to webjs identity: no-build, progressive enhancement, web-components-first, AI-first, batteries-included, close to web standards.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions