Skip to content

Commit a46f27f

Browse files
authored
Use provided waitUntil for pending revalidates (#74164) (#74604)
This backports #74164 to leverage built-in waitUntil if available instead of using the approach that keeps the stream open until the waitUntil promise resolves. x-ref: [slack thread](https://vercel.slack.com/archives/C02K2HCH5V4/p1736211642221149?thread_ts=1734707275.666089&cid=C02K2HCH5V4)
1 parent bc6acf6 commit a46f27f

File tree

4 files changed

+47
-11
lines changed

4 files changed

+47
-11
lines changed

packages/next/src/server/app-render/app-render.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,13 +1276,23 @@ async function renderToHTMLOrFlightImpl(
12761276
workStore.pendingRevalidateWrites ||
12771277
workStore.revalidatedTags
12781278
) {
1279-
options.waitUntil = Promise.all([
1279+
const pendingPromise = Promise.all([
12801280
workStore.incrementalCache?.revalidateTag(
12811281
workStore.revalidatedTags || []
12821282
),
12831283
...Object.values(workStore.pendingRevalidates || {}),
12841284
...(workStore.pendingRevalidateWrites || []),
1285-
])
1285+
]).finally(() => {
1286+
if (process.env.NEXT_PRIVATE_DEBUG_CACHE) {
1287+
console.log('pending revalidates promise finished for:', url)
1288+
}
1289+
})
1290+
1291+
if (renderOpts.waitUntil) {
1292+
renderOpts.waitUntil(pendingPromise)
1293+
} else {
1294+
options.waitUntil = pendingPromise
1295+
}
12861296
}
12871297

12881298
if (response.collectedTags) {
@@ -1433,13 +1443,23 @@ async function renderToHTMLOrFlightImpl(
14331443
workStore.pendingRevalidateWrites ||
14341444
workStore.revalidatedTags
14351445
) {
1436-
options.waitUntil = Promise.all([
1446+
const pendingPromise = Promise.all([
14371447
workStore.incrementalCache?.revalidateTag(
14381448
workStore.revalidatedTags || []
14391449
),
14401450
...Object.values(workStore.pendingRevalidates || {}),
14411451
...(workStore.pendingRevalidateWrites || []),
1442-
])
1452+
]).finally(() => {
1453+
if (process.env.NEXT_PRIVATE_DEBUG_CACHE) {
1454+
console.log('pending revalidates promise finished for:', url)
1455+
}
1456+
})
1457+
1458+
if (renderOpts.waitUntil) {
1459+
renderOpts.waitUntil(pendingPromise)
1460+
} else {
1461+
options.waitUntil = pendingPromise
1462+
}
14431463
}
14441464

14451465
// Create the new render result for the response.

packages/next/src/server/base-server.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,6 +2541,16 @@ export default abstract class Server<
25412541

25422542
return cacheEntry
25432543
}
2544+
let pendingWaitUntil = context.renderOpts.pendingWaitUntil
2545+
2546+
// Attempt using provided waitUntil if available
2547+
// if it's not we fallback to sendResponse's handling
2548+
if (pendingWaitUntil) {
2549+
if (context.renderOpts.waitUntil) {
2550+
context.renderOpts.waitUntil(pendingWaitUntil)
2551+
pendingWaitUntil = undefined
2552+
}
2553+
}
25442554

25452555
// Send the response now that we have copied it into the cache.
25462556
await sendResponse(

packages/next/src/server/route-modules/app-route/module.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,14 @@ export class AppRouteRouteModule extends RouteModule<
597597
workStore.revalidatedTags || []
598598
),
599599
...Object.values(workStore.pendingRevalidates || {}),
600-
])
600+
]).finally(() => {
601+
if (process.env.NEXT_PRIVATE_DEBUG_CACHE) {
602+
console.log(
603+
'pending revalidates promise finished for:',
604+
requestStore.url
605+
)
606+
}
607+
})
601608

602609
if (prerenderStore) {
603610
context.renderOpts.collectedTags = prerenderStore.tags?.join(',')

test/e2e/app-dir/app-fetch-deduping/app-fetch-deduping.test.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { findPort, waitFor } from 'next-test-utils'
1+
import { findPort, retry } from 'next-test-utils'
22
import http from 'http'
33
import url from 'url'
44
import { outdent } from 'outdent'
@@ -112,11 +112,10 @@ describe('app-fetch-deduping', () => {
112112
expect(invocation(next.cliOutput)).toBe(1)
113113

114114
// wait for the revalidation to finish
115-
await waitFor(revalidate * 1000 + 1000)
116-
117-
await next.render('/test')
118-
119-
expect(invocation(next.cliOutput)).toBe(2)
115+
await retry(async () => {
116+
await next.render('/test')
117+
expect(invocation(next.cliOutput)).toBe(2)
118+
}, 10_000)
120119
})
121120
})
122121
} else {

0 commit comments

Comments
 (0)