Skip to content

Commit

Permalink
fix: track revalidate / cdn purge to ensure it finishes execution and…
Browse files Browse the repository at this point in the history
… is not suspended mid-execution
  • Loading branch information
pieh committed Jun 17, 2024
1 parent 063027c commit c6a8699
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
28 changes: 21 additions & 7 deletions src/run/handlers/cache.cts
Original file line number Diff line number Diff line change
Expand Up @@ -244,19 +244,33 @@ export class NetlifyCacheHandler implements CacheHandler {
if (requestContext?.didPagesRouterOnDemandRevalidate) {
const tag = `_N_T_${key === '/index' ? '/' : key}`
getLogger().debug(`Purging CDN cache for: [${tag}]`)
purgeCache({ tags: [tag] }).catch((error) => {
// TODO: add reporting here
getLogger()
.withError(error)
.error(`[NetlifyCacheHandler]: Purging the cache for tag ${tag} failed`)
})
requestContext.trackBackgroundWork(
purgeCache({ tags: [tag] }).catch((error) => {
// TODO: add reporting here
getLogger()
.withError(error)
.error(`[NetlifyCacheHandler]: Purging the cache for tag ${tag} failed`)
}),
)
}
}
})
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async revalidateTag(tagOrTags: string | string[], ...args: any) {
const revalidateTagPromise = this.doRevalidateTag(tagOrTags, ...args)

const requestContext = getRequestContext()
if (requestContext) {
requestContext.trackBackgroundWork(revalidateTagPromise)
}

return revalidateTagPromise
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private async doRevalidateTag(tagOrTags: string | string[], ...args: any) {
getLogger().withFields({ tagOrTags, args }).debug('NetlifyCacheHandler.revalidateTag')

const tags = Array.isArray(tagOrTags) ? tagOrTags : [tagOrTags]
Expand All @@ -275,7 +289,7 @@ export class NetlifyCacheHandler implements CacheHandler {
}),
)

purgeCache({ tags }).catch((error) => {
await purgeCache({ tags }).catch((error) => {
// TODO: add reporting here
getLogger()
.withError(error)
Expand Down
9 changes: 8 additions & 1 deletion src/run/revalidate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ServerResponse } from 'node:http'
import { isPromise } from 'node:util/types'

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

Expand All @@ -12,7 +13,13 @@ export const nextResponseProxy = (res: ServerResponse, requestContext: RequestCo
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return async function newRevalidate(...args: any[]) {
requestContext.didPagesRouterOnDemandRevalidate = true
return originalValue?.apply(target, args)

const result = originalValue?.apply(target, args)
if (result && isPromise(result)) {
requestContext.trackBackgroundWork(result)
}

return result
}
}
return originalValue
Expand Down
5 changes: 4 additions & 1 deletion tests/fixtures/page-router/pages/api/revalidate.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export default async function handler(req, res) {
try {
await res.revalidate('/static/revalidate-manual')
// res.revalidate returns a promise that can be awaited to wait for the revalidation to complete
// if user doesn't await it, we still want to ensure the revalidation is completed, so we internally track
// this as "background work" to ensure it completes before function suspends execution
res.revalidate('/static/revalidate-manual')
return res.json({ code: 200, message: 'success' })
} catch (err) {
return res.status(500).send({ code: 500, message: err.message })
Expand Down

0 comments on commit c6a8699

Please sign in to comment.