@@ -52,6 +52,29 @@ 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+ if ( revalidate === false ) {
71+ return 'PERMANENT'
72+ }
73+ }
74+
75+ return 'NOT SET'
76+ }
77+
5578 private captureResponseCacheLastModified (
5679 cacheValue : NetlifyCacheHandlerValue ,
5780 key : string ,
@@ -219,10 +242,31 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
219242 return null
220243 }
221244
245+ const ttl = this . getTTL ( blob )
246+
247+ if ( getRequestContext ( ) ?. isBackgroundRevalidation && typeof ttl === 'number' && ttl < 0 ) {
248+ // background revalidation request should allow data that is not yet stale,
249+ // but opt to discard STALE data, so that Next.js generate fresh response
250+ span . addEvent ( 'Discarding stale entry due to SWR background revalidation request' , {
251+ key,
252+ blobKey,
253+ ttl,
254+ } )
255+ getLogger ( )
256+ . withFields ( {
257+ ttl,
258+ key,
259+ } )
260+ . debug (
261+ `[NetlifyCacheHandler.get] Discarding stale entry due to SWR background revalidation request: ${ key } ` ,
262+ )
263+ return null
264+ }
265+
222266 const staleByTags = await this . checkCacheEntryStaleByTags ( blob , ctx . tags , ctx . softTags )
223267
224268 if ( staleByTags ) {
225- span . addEvent ( 'Stale' , { staleByTags } )
269+ span . addEvent ( 'Stale' , { staleByTags, key , blobKey , ttl } )
226270 return null
227271 }
228272
@@ -231,7 +275,11 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
231275
232276 switch ( blob . value ?. kind ) {
233277 case 'FETCH' :
234- span . addEvent ( 'FETCH' , { lastModified : blob . lastModified , revalidate : ctx . revalidate } )
278+ span . addEvent ( 'FETCH' , {
279+ lastModified : blob . lastModified ,
280+ revalidate : ctx . revalidate ,
281+ ttl,
282+ } )
235283 return {
236284 lastModified : blob . lastModified ,
237285 value : blob . value ,
@@ -242,6 +290,8 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
242290 span . addEvent ( blob . value ?. kind , {
243291 lastModified : blob . lastModified ,
244292 status : blob . value . status ,
293+ revalidate : blob . value . revalidate ,
294+ ttl,
245295 } )
246296
247297 const valueWithoutRevalidate = this . captureRouteRevalidateAndRemoveFromObject ( blob . value )
@@ -256,10 +306,10 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
256306 }
257307 case 'PAGE' :
258308 case 'PAGES' : {
259- span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified } )
260-
261309 const { revalidate, ...restOfPageValue } = blob . value
262310
311+ span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified , revalidate, ttl } )
312+
263313 await this . injectEntryToPrerenderManifest ( key , revalidate )
264314
265315 return {
@@ -268,10 +318,10 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
268318 }
269319 }
270320 case 'APP_PAGE' : {
271- span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified } )
272-
273321 const { revalidate, rscData, ...restOfPageValue } = blob . value
274322
323+ span . addEvent ( blob . value ?. kind , { lastModified : blob . lastModified , revalidate, ttl } )
324+
275325 await this . injectEntryToPrerenderManifest ( key , revalidate )
276326
277327 return {
0 commit comments