@@ -52,6 +52,27 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
5252 return await encodeBlobKey ( key )
5353 }
5454
55+ private getTTL ( blob : NetlifyCacheHandlerValue ) {
56+ if (
57+ blob . value ?. kind === 'FETCH' ||
58+ blob . value ?. kind === 'ROUTE' ||
59+ blob . value ?. kind === 'APP_ROUTE' ||
60+ blob . value ?. kind === 'PAGE' ||
61+ blob . value ?. kind === 'PAGES' ||
62+ blob . value ?. kind === 'APP_PAGE'
63+ ) {
64+ const { revalidate } = blob . value
65+
66+ if ( typeof revalidate === 'number' ) {
67+ const revalidateAfter = revalidate * 1_000 + blob . lastModified
68+ return ( revalidateAfter - Date . now ( ) ) / 1_000
69+ }
70+ return revalidate === false ? 'PERMANENT' : 'NOT SET'
71+ }
72+
73+ return 'NOT SET'
74+ }
75+
5576 private captureResponseCacheLastModified (
5677 cacheValue : NetlifyCacheHandlerValue ,
5778 key : string ,
@@ -219,10 +240,31 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
219240 return null
220241 }
221242
243+ const ttl = this . getTTL ( blob )
244+
245+ if ( getRequestContext ( ) ?. isBackgroundRevalidation && typeof ttl === 'number' && ttl < 0 ) {
246+ // background revalidation request should allow data that is not yet stale,
247+ // but opt to discard STALE data, so that Next.js generate fresh response
248+ span . addEvent ( 'Discarding stale entry due to SWR background revalidation request' , {
249+ key,
250+ blobKey,
251+ ttl,
252+ } )
253+ getLogger ( )
254+ . withFields ( {
255+ ttl,
256+ key,
257+ } )
258+ . debug (
259+ `[NetlifyCacheHandler.get] Discarding stale entry due to SWR background revalidation request: ${ key } ` ,
260+ )
261+ return null
262+ }
263+
222264 const staleByTags = await this . checkCacheEntryStaleByTags ( blob , ctx . tags , ctx . softTags )
223265
224266 if ( staleByTags ) {
225- span . addEvent ( 'Stale' , { staleByTags } )
267+ span . addEvent ( 'Stale' , { staleByTags, key , blobKey , ttl } )
226268 return null
227269 }
228270
@@ -231,7 +273,11 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
231273
232274 switch ( blob . value ?. kind ) {
233275 case 'FETCH' :
234- span . addEvent ( 'FETCH' , { lastModified : blob . lastModified , revalidate : ctx . revalidate } )
276+ span . addEvent ( 'FETCH' , {
277+ lastModified : blob . lastModified ,
278+ revalidate : ctx . revalidate ,
279+ ttl,
280+ } )
235281 return {
236282 lastModified : blob . lastModified ,
237283 value : blob . value ,
@@ -242,6 +288,8 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
242288 span . addEvent ( blob . value ?. kind , {
243289 lastModified : blob . lastModified ,
244290 status : blob . value . status ,
291+ revalidate : blob . value . revalidate ,
292+ ttl,
245293 } )
246294
247295 const valueWithoutRevalidate = this . captureRouteRevalidateAndRemoveFromObject ( blob . value )
@@ -256,10 +304,10 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
256304 }
257305 case 'PAGE' :
258306 case 'PAGES' : {
259- span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified } )
260-
261307 const { revalidate, ...restOfPageValue } = blob . value
262308
309+ span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified , revalidate, ttl } )
310+
263311 await this . injectEntryToPrerenderManifest ( key , revalidate )
264312
265313 return {
@@ -268,10 +316,10 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
268316 }
269317 }
270318 case 'APP_PAGE' : {
271- span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified } )
272-
273319 const { revalidate, rscData, ...restOfPageValue } = blob . value
274320
321+ span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified , revalidate, ttl } )
322+
275323 await this . injectEntryToPrerenderManifest ( key , revalidate )
276324
277325 return {
0 commit comments