Skip to content

Commit

Permalink
fix(fetch-cache): fix additional typo, add type & data validation (#6…
Browse files Browse the repository at this point in the history
…4799)

This PR fixes the fetch cache, which currently is not using the fetch
cache when it exists (the tags were not getting set properly), and tags
have not updated.

(Before)

https://github.com/vercel/next.js/assets/28912696/74d8f592-0698-4ae4-be4b-30cffb1ffe11

(After)

https://github.com/vercel/next.js/assets/28912696/af12b13a-46c6-41c3-9ac3-20e1ec44a865

- #64786
- #63547

Closes NEXT-3173
  • Loading branch information
samcx authored and huozhi committed Apr 23, 2024
1 parent 4a6b511 commit d6a7ca0
Showing 1 changed file with 29 additions and 6 deletions.
35 changes: 29 additions & 6 deletions packages/next/src/server/lib/incremental-cache/fetch-cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import type { CacheHandler, CacheHandlerContext, CacheHandlerValue } from './'
import type {
CachedFetchValue,
IncrementalCacheValue,
} from '../../response-cache'

import LRUCache from 'next/dist/compiled/lru-cache'

import { z } from 'next/dist/compiled/zod'
import type zod from 'next/dist/compiled/zod'

import {
CACHE_ONE_YEAR,
NEXT_CACHE_SOFT_TAGS_HEADER,
Expand All @@ -23,6 +31,18 @@ const CACHE_REVALIDATE_HEADER = 'x-vercel-revalidate' as const
const CACHE_FETCH_URL_HEADER = 'x-vercel-cache-item-name' as const
const CACHE_CONTROL_VALUE_HEADER = 'x-vercel-cache-control' as const

const zCachedFetchValue: zod.ZodType<CachedFetchValue> = z.object({
kind: z.literal('FETCH'),
data: z.object({
headers: z.record(z.string()),
body: z.string(),
url: z.string(),
status: z.number().optional(),
}),
tags: z.array(z.string()).optional(),
revalidate: z.number(),
})

export default class FetchCache implements CacheHandler {
private headers: Record<string, string>
private cacheEndpoint?: string
Expand Down Expand Up @@ -233,19 +253,22 @@ export default class FetchCache implements CacheHandler {
throw new Error(`invalid response from cache ${res.status}`)
}

const cached = await res.json()
const json: IncrementalCacheValue = await res.json()
const parsed = zCachedFetchValue.safeParse(json)

if (!cached || cached.kind !== 'FETCH') {
this.debug && console.log({ cached })
throw new Error(`invalid cache value`)
if (!parsed.success) {
this.debug && console.log({ json })
throw new Error('invalid cache value')
}

const { data: cached } = parsed

// if new tags were specified, merge those tags to the existing tags
if (cached.kind === 'FETCH') {
cached.tags ??= []
for (const tag of tags ?? []) {
if (!cached.tags.include(tag)) {
cached.tag.push(tag)
if (!cached.tags.includes(tag)) {
cached.tags.push(tag)
}
}
}
Expand Down

0 comments on commit d6a7ca0

Please sign in to comment.