Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test to verify that inner caches are excluded from Resume Data Cache #75883

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/next/src/server/resume-data-cache/cache-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import type { CachedFetchValue } from '../response-cache/types'
/**
* A generic cache store type that provides a subset of Map functionality
*/
type CacheStore<T> = Pick<Map<string, T>, 'entries' | 'size' | 'get' | 'set'>
type CacheStore<T> = Pick<
Map<string, T>,
'entries' | 'keys' | 'size' | 'get' | 'set'
>

/**
* A cache store specifically for fetch cache values
Expand Down
33 changes: 33 additions & 0 deletions test/e2e/app-dir/use-cache/app/rdc/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { connection } from 'next/server'
import { Suspense } from 'react'

async function outermost(id: string) {
'use cache'
return id + middle('middle')
}

async function middle(id: string) {
'use cache'
return id + innermost('inner')
}

async function innermost(id: string) {
'use cache'
return id
}

async function Dynamic() {
await connection()
return null
}

export default async function Page() {
await outermost('outer')
await innermost('inner')

return (
<Suspense>
<Dynamic />
</Suspense>
)
}
36 changes: 36 additions & 0 deletions test/e2e/app-dir/use-cache/use-cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { retry, waitFor } from 'next-test-utils'
import stripAnsi from 'strip-ansi'
import { format } from 'util'
import { BrowserInterface } from 'next-webdriver'
import {
createRenderResumeDataCache,
RenderResumeDataCache,
} from 'next/dist/server/resume-data-cache/resume-data-cache'

const GENERIC_RSC_ERROR =
'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.'
Expand Down Expand Up @@ -596,6 +600,27 @@ describe('use-cache', () => {
})
})
}

if (isNextStart && process.env.__NEXT_EXPERIMENTAL_PPR === 'true') {
it('should exclude inner caches from the resume data cache (RDC)', async () => {
await next.fetch('/rdc')

const resumeDataCache = extractResumeDataCacheFromPostponedState(
JSON.parse(await next.readFile('.next/server/app/rdc.meta')).postponed
)

const cacheKeys = Array.from(resumeDataCache.cache.keys())

// There should be no cache entry for the "middle" cache function, because
// it's only used inside another cache scope ("outer"). Whereas "inner" is
// also used inside a prerender scope (the page). Note: We're matching on
// the "id" args that are encoded into the respective cache keys.
expect(cacheKeys).toMatchObject([
expect.stringContaining('["outer"]'),
expect.stringContaining('["inner"]'),
])
})
}
})

async function getSanitizedLogs(browser: BrowserInterface): Promise<string[]> {
Expand All @@ -607,3 +632,14 @@ async function getSanitizedLogs(browser: BrowserInterface): Promise<string[]> {
)
)
}

function extractResumeDataCacheFromPostponedState(
state: string
): RenderResumeDataCache {
const postponedStringLengthMatch = state.match(/^([0-9]*):/)![1]
const postponedStringLength = parseInt(postponedStringLengthMatch)

return createRenderResumeDataCache(
state.slice(postponedStringLengthMatch.length + postponedStringLength + 1)
)
}
Loading