@@ -8,6 +8,8 @@ import { getCloudflareContext } from "./get-cloudflare-context.js";
88
99export const CACHE_ASSET_DIR = "cnd-cgi/_next_cache" ;
1010
11+ export const STATUS_DELETED = 1 ;
12+
1113/**
1214 * Open Next cache based on cloudflare KV and Assets.
1315 *
@@ -38,26 +40,32 @@ class Cache implements IncrementalCache {
3840 try {
3941 this . debug ( `- From KV` ) ;
4042 const kvKey = this . getKVKey ( key , isFetch ? "fetch" : "cache" ) ;
41- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42- let value : any = await this . kv ?. get ( kvKey , "json" ) ;
43- if ( ! value && this . assets ) {
43+
44+ let entry = ( await this . kv ?. get ( kvKey , "json" ) ) as {
45+ value ?: CacheValue < IsFetch > ;
46+ lastModified ?: number ;
47+ status ?: number ;
48+ } | null ;
49+ if ( entry ?. status === STATUS_DELETED ) {
50+ return { } ;
51+ }
52+ if ( ! entry && this . assets ) {
4453 const url = this . getAssetUrl ( key ) ;
4554 const response = await this . assets . fetch ( url ) ;
4655 this . debug ( `- From Assets` ) ;
4756 if ( response . ok ) {
48- value = await response . json ( ) ;
57+ entry = {
58+ value : await response . json ( ) ,
59+ // __BUILD_TIMESTAMP_MS__ is injected by ESBuild.
60+ lastModified : ( globalThis as { __BUILD_TIMESTAMP_MS__ ?: number } ) . __BUILD_TIMESTAMP_MS__ ,
61+ } ;
4962 }
5063 }
51- if ( value ) {
52- this . debug ( `-> hit` ) ;
53- return { value } ;
54- }
64+ this . debug ( entry ? `-> hit` : `-> miss` ) ;
65+ return { value : entry ?. value , lastModified : entry ?. lastModified } ;
5566 } catch {
5667 throw new RecoverableError ( `Failed to get cache [${ key } ]` ) ;
5768 }
58-
59- this . debug ( `-> miss` ) ;
60- throw new RecoverableError ( `Not found [${ key } ]` ) ;
6169 }
6270
6371 async set < IsFetch extends boolean = false > (
@@ -74,8 +82,16 @@ class Cache implements IncrementalCache {
7482 this . debug ( `Set ${ key } ` ) ;
7583 try {
7684 const kvKey = this . getKVKey ( key , isFetch ? "fetch" : "cache" ) ;
77- // TODO: add TTL to avoid cache growing too big ?
78- await this . kv . put ( kvKey , JSON . stringify ( value ) ) ;
85+ // Note: We can not set a TTL as we might fallback to assets,
86+ // still removing old data (old BUILD_ID) could help avoiding
87+ // the cache growing too big.
88+ await this . kv . put (
89+ kvKey ,
90+ JSON . stringify ( {
91+ value,
92+ lastModified : Date . now ( ) ,
93+ } )
94+ ) ;
7995 } catch {
8096 throw new RecoverableError ( `Failed to set cache [${ key } ]` ) ;
8197 }
@@ -91,7 +107,8 @@ class Cache implements IncrementalCache {
91107 this . debug ( `Delete ${ key } ` ) ;
92108 try {
93109 const kvKey = this . getKVKey ( key , "cache" ) ;
94- await this . kv . delete ( kvKey ) ;
110+ // Do not delete the key as we will then fallback to the assets.
111+ await this . kv . put ( kvKey , JSON . stringify ( { status : STATUS_DELETED } ) ) ;
95112 } catch ( e ) {
96113 throw new RecoverableError ( `Failed to delete cache [${ key } ]` ) ;
97114 }
0 commit comments