next.js
323a17c1 - [backport] Discard only cache entries that predate a tag revalidation, and reuse completed entries (#97314)

Commit
54 days ago
[backport] Discard only cache entries that predate a tag revalidation, and reuse completed entries (#97314) Backports #96726 ("Discard only cache entries that predate a tag revalidation") and #96727 ("Reuse completed cache entries for the rest of a request") to `next-16-3`. Calling `updateTag()` in a server action made every later read of a cache carrying that tag regenerate for the remainder of the request, including reads of an entry that had just been generated after the invalidation and therefore already reflected it. Two sequential reads of the same cache function during the re-render produced two different values within a single render, and each one repeated the work. `isRecentlyRevalidatedTag` only asked whether a tag appeared in `pendingRevalidatedTags`, and that array lives for the whole `WorkStore`, which spans a server action and the render that follows it. Each pending revalidated tag now records a `revalidatedAt` timestamp taken from the same clock as `CacheEntry.timestamp`, and the renamed `isRevalidatedAfter` reports an entry as stale only when the revalidation is newer than the entry. The second change fixes a `'use cache: private'` function executing its body twice when it is called twice in one request, which defeats the preload-then-read shape that motivates a preload in the first place. The intra-request dedupe map dropped an entry as soon as its fill completed, so it only ever covered concurrent invocations, and private caches have no cache handler in production to fall back to. Completed invocations now move into `completedCacheInvocations` on the work store instead of being dropped. The two are backported together because #96727 builds on the discard checks that #96726 restructures. They were stacked in this order on canary, and #96727 conflicts in `test/e2e/app-dir/use-cache/use-cache.test.ts` when applied alone. ### Verification on this branch Cherry-picked from `5da1c1ae03` and `1ff6a80358` in that order, with no conflicts. All source files are byte-identical to canary. Behavioral verification is left to CI on this branch; the changes carry the `action-dedupe`, `dedup-sequential` and `private-dedup-sequential` fixtures in the `use-cache` suite, and a handler-call count assertion in `use-cache-custom-handler`. <!-- NEXT_JS_LLM -->
Author
Parents
Loading