@@ -2,17 +2,55 @@ import { purgeCache } from '@netlify/functions'
2
2
3
3
import { name as nextRuntimePkgName , version as nextRuntimePkgVersion } from '../../../package.json'
4
4
import { TagManifest } from '../../shared/blob-types.cjs'
5
- import { getMemoizedKeyValueStoreBackedByRegionalBlobStore } from '../storage/storage.cjs'
5
+ import {
6
+ getMemoizedKeyValueStoreBackedByRegionalBlobStore ,
7
+ MemoizedKeyValueStoreBackedByRegionalBlobStore ,
8
+ } from '../storage/storage.cjs'
6
9
7
10
import { getLogger , getRequestContext } from './request-context.cjs'
8
11
9
12
const purgeCacheUserAgent = `${ nextRuntimePkgName } @${ nextRuntimePkgVersion } `
10
13
14
+ /**
15
+ * Get timestamp of the last revalidation for a tag
16
+ */
17
+ async function lastTagRevalidationTimestamp (
18
+ tag : string ,
19
+ cacheStore : MemoizedKeyValueStoreBackedByRegionalBlobStore ,
20
+ ) : Promise < number | null > {
21
+ const tagManifest = await cacheStore . get < TagManifest > ( tag , 'tagManifest.get' )
22
+ if ( ! tagManifest ) {
23
+ return null
24
+ }
25
+ return tagManifest . revalidatedAt
26
+ }
27
+
28
+ /**
29
+ *
30
+ */
31
+ export async function getMostRecentTagRevalidationTimestamp ( tags : string [ ] ) {
32
+ if ( tags . length === 0 ) {
33
+ return 0
34
+ }
35
+
36
+ const cacheStore = getMemoizedKeyValueStoreBackedByRegionalBlobStore ( { consistency : 'strong' } )
37
+
38
+ const timestampsOrNulls = await Promise . all (
39
+ tags . map ( ( tag ) => lastTagRevalidationTimestamp ( tag , cacheStore ) ) ,
40
+ )
41
+
42
+ const timestamps = timestampsOrNulls . filter ( ( timestamp ) => timestamp !== null )
43
+ if ( timestamps . length === 0 ) {
44
+ return 0
45
+ }
46
+ return Math . max ( ...timestamps )
47
+ }
48
+
11
49
/**
12
50
* Check if any of the tags were invalidated since the given timestamp
13
51
*/
14
52
export function isAnyTagStale ( tags : string [ ] , timestamp : number ) : Promise < boolean > {
15
- if ( tags . length === 0 ) {
53
+ if ( tags . length === 0 || ! timestamp ) {
16
54
return Promise . resolve ( false )
17
55
}
18
56
@@ -22,17 +60,14 @@ export function isAnyTagStale(tags: string[], timestamp: number): Promise<boolea
22
60
const tagManifestPromises : Promise < boolean > [ ] = [ ]
23
61
24
62
for ( const tag of tags ) {
25
- const tagManifestPromise : Promise < TagManifest | null > = cacheStore . get < TagManifest > (
26
- tag ,
27
- 'tagManifest.get' ,
28
- )
63
+ const lastRevalidationTimestampPromise = lastTagRevalidationTimestamp ( tag , cacheStore )
29
64
30
65
tagManifestPromises . push (
31
- tagManifestPromise . then ( ( tagManifest ) => {
32
- if ( ! tagManifest ) {
66
+ lastRevalidationTimestampPromise . then ( ( lastRevalidationTimestamp ) => {
67
+ if ( ! lastRevalidationTimestamp ) {
33
68
return false
34
69
}
35
- const isStale = tagManifest . revalidatedAt >= ( timestamp || Date . now ( ) )
70
+ const isStale = lastRevalidationTimestamp >= timestamp
36
71
if ( isStale ) {
37
72
resolve ( true )
38
73
return true
0 commit comments