Skip to content

Commit b665b3b

Browse files
committed
Merge remote-tracking branch 'origin/fix/track-background-revalidation' into tmp/shared-timings-and-background-track
2 parents eb14049 + bd9771b commit b665b3b

File tree

5 files changed

+72
-13
lines changed

5 files changed

+72
-13
lines changed

src/run/handlers/cache.cts

+21-7
Original file line numberDiff line numberDiff line change
@@ -283,19 +283,33 @@ export class NetlifyCacheHandler implements CacheHandler {
283283
if (requestContext?.didPagesRouterOnDemandRevalidate) {
284284
const tag = `_N_T_${key === '/index' ? '/' : key}`
285285
getLogger().debug(`Purging CDN cache for: [${tag}]`)
286-
purgeCache({ tags: [tag] }).catch((error) => {
287-
// TODO: add reporting here
288-
getLogger()
289-
.withError(error)
290-
.error(`[NetlifyCacheHandler]: Purging the cache for tag ${tag} failed`)
291-
})
286+
requestContext.trackBackgroundWork(
287+
purgeCache({ tags: [tag] }).catch((error) => {
288+
// TODO: add reporting here
289+
getLogger()
290+
.withError(error)
291+
.error(`[NetlifyCacheHandler]: Purging the cache for tag ${tag} failed`)
292+
}),
293+
)
292294
}
293295
}
294296
})
295297
}
296298

297299
// eslint-disable-next-line @typescript-eslint/no-explicit-any
298300
async revalidateTag(tagOrTags: string | string[], ...args: any) {
301+
const revalidateTagPromise = this.doRevalidateTag(tagOrTags, ...args)
302+
303+
const requestContext = getRequestContext()
304+
if (requestContext) {
305+
requestContext.trackBackgroundWork(revalidateTagPromise)
306+
}
307+
308+
return revalidateTagPromise
309+
}
310+
311+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
312+
private async doRevalidateTag(tagOrTags: string | string[], ...args: any) {
299313
getLogger().withFields({ tagOrTags, args }).debug('NetlifyCacheHandler.revalidateTag')
300314

301315
const tags = Array.isArray(tagOrTags) ? tagOrTags : [tagOrTags]
@@ -314,7 +328,7 @@ export class NetlifyCacheHandler implements CacheHandler {
314328
}),
315329
)
316330

317-
purgeCache({ tags }).catch((error) => {
331+
await purgeCache({ tags }).catch((error) => {
318332
// TODO: add reporting here
319333
getLogger()
320334
.withError(error)

src/run/revalidate.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { ServerResponse } from 'node:http'
2+
import { isPromise } from 'node:util/types'
23

34
import type { RequestContext } from './handlers/request-context.cjs'
45

@@ -12,7 +13,13 @@ export const nextResponseProxy = (res: ServerResponse, requestContext: RequestCo
1213
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1314
return async function newRevalidate(...args: any[]) {
1415
requestContext.didPagesRouterOnDemandRevalidate = true
15-
return originalValue?.apply(target, args)
16+
17+
const result = originalValue?.apply(target, args)
18+
if (result && isPromise(result)) {
19+
requestContext.trackBackgroundWork(result)
20+
}
21+
22+
return result
1623
}
1724
}
1825
return originalValue

tests/fixtures/page-router/pages/api/revalidate.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
export default async function handler(req, res) {
22
try {
3-
await res.revalidate('/static/revalidate-manual')
3+
// res.revalidate returns a promise that can be awaited to wait for the revalidation to complete
4+
// if user doesn't await it, we still want to ensure the revalidation is completed, so we internally track
5+
// this as "background work" to ensure it completes before function suspends execution
6+
res.revalidate('/static/revalidate-manual')
47
return res.json({ code: 200, message: 'success' })
58
} catch (err) {
69
return res.status(500).send({ code: 500, message: err.message })

tests/utils/fixture.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -364,14 +364,24 @@ export async function invokeFunction(
364364
NETLIFY_BLOBS_CONTEXT: createBlobContext(ctx),
365365
...(env || {}),
366366
}
367+
368+
const envVarsToRestore = {}
369+
370+
// We are not using lambda-local's environment variable setting because it cleans up
371+
// environment vars to early (before stream is closed)
372+
Object.keys(environment).forEach(function (key) {
373+
if (typeof process.env[key] !== 'undefined') {
374+
envVarsToRestore[key] = process.env[key]
375+
}
376+
process.env[key] = environment[key]
377+
})
378+
367379
const response = (await execute({
368380
event: {
369381
headers: headers || {},
370382
httpMethod: httpMethod || 'GET',
371383
rawUrl: new URL(url || '/', 'https://example.netlify').href,
372384
},
373-
environment,
374-
envdestroy: true,
375385
lambdaFunc: { handler },
376386
timeoutMs: 4_000,
377387
})) as LambdaResponse
@@ -386,6 +396,14 @@ export async function invokeFunction(
386396

387397
const bodyBuffer = await streamToBuffer(response.body)
388398

399+
Object.keys(environment).forEach(function (key) {
400+
if (typeof envVarsToRestore[key] !== 'undefined') {
401+
process.env[key] = envVarsToRestore[key]
402+
} else {
403+
delete process.env[key]
404+
}
405+
})
406+
389407
return {
390408
statusCode: response.statusCode,
391409
bodyBuffer,

tests/utils/sandbox-child.mjs

+19-2
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,23 @@ process.on('message', async (msg) => {
4848
...(env || {}),
4949
}
5050

51+
const envVarsToRestore = {}
52+
53+
// We are not using lambda-local's environment variable setting because it cleans up
54+
// environment vars to early (before stream is closed)
55+
Object.keys(environment).forEach(function (key) {
56+
if (typeof process.env[key] !== 'undefined') {
57+
envVarsToRestore[key] = process.env[key]
58+
}
59+
process.env[key] = environment[key]
60+
})
61+
5162
const response = await execute({
5263
event: {
5364
headers: headers || {},
5465
httpMethod: httpMethod || 'GET',
5566
rawUrl: new URL(url || '/', 'https://example.netlify').href,
5667
},
57-
environment,
58-
envdestroy: true,
5968
lambdaFunc: { handler },
6069
timeoutMs: 4_000,
6170
})
@@ -70,6 +79,14 @@ process.on('message', async (msg) => {
7079

7180
const bodyBuffer = await streamToBuffer(response.body)
7281

82+
Object.keys(environment).forEach(function (key) {
83+
if (typeof envVarsToRestore[key] !== 'undefined') {
84+
process.env[key] = envVarsToRestore[key]
85+
} else {
86+
delete process.env[key]
87+
}
88+
})
89+
7390
const result = {
7491
statusCode: response.statusCode,
7592
bodyBuffer,

0 commit comments

Comments
 (0)