-
Notifications
You must be signed in to change notification settings - Fork 118
Expand file tree
/
Copy pathr2-incremental-cache.ts
More file actions
91 lines (74 loc) · 2.52 KB
/
r2-incremental-cache.ts
File metadata and controls
91 lines (74 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { error } from "@opennextjs/aws/adapters/logger.js";
import type {
CacheEntryType,
CacheValue,
IncrementalCache,
WithLastModified,
} from "@opennextjs/aws/types/overrides.js";
import { IgnorableError } from "@opennextjs/aws/utils/error.js";
import { getCloudflareContext } from "../../cloudflare-context.js";
import { computeCacheKey, debugCache } from "../internal.js";
export const NAME = "cf-r2-incremental-cache";
export const BINDING_NAME = "NEXT_INC_CACHE_R2_BUCKET";
export const PREFIX_ENV_NAME = "NEXT_INC_CACHE_R2_PREFIX";
/**
* An instance of the Incremental Cache that uses an R2 bucket (`NEXT_INC_CACHE_R2_BUCKET`) as it's
* underlying data store.
*
* The directory that the cache entries are stored in can be configured with the `NEXT_INC_CACHE_R2_PREFIX`
* environment variable, and defaults to `incremental-cache`.
*/
class R2IncrementalCache implements IncrementalCache {
readonly name: string = NAME;
async get<CacheType extends CacheEntryType = "cache">(
key: string,
cacheType?: CacheType
): Promise<WithLastModified<CacheValue<CacheType>> | null> {
const r2 = getCloudflareContext().env[BINDING_NAME];
if (!r2) throw new IgnorableError("No R2 bucket");
debugCache("R2IncrementalCache", `get ${key}`);
try {
const r2Object = await r2.get(this.getR2Key(key, cacheType));
if (!r2Object) return null;
return {
value: await r2Object.json(),
lastModified: r2Object.uploaded.getTime(),
};
} catch (e) {
error("Failed to get from cache", e);
return null;
}
}
async set<CacheType extends CacheEntryType = "cache">(
key: string,
value: CacheValue<CacheType>,
cacheType?: CacheType
): Promise<void> {
const r2 = getCloudflareContext().env[BINDING_NAME];
if (!r2) throw new IgnorableError("No R2 bucket");
debugCache("R2IncrementalCache", `set ${key}`);
try {
await r2.put(this.getR2Key(key, cacheType), JSON.stringify(value));
} catch (e) {
error("Failed to set to cache", e);
}
}
async delete(key: string): Promise<void> {
const r2 = getCloudflareContext().env[BINDING_NAME];
if (!r2) throw new IgnorableError("No R2 bucket");
debugCache("R2IncrementalCache", `delete ${key}`);
try {
await r2.delete(this.getR2Key(key));
} catch (e) {
error("Failed to delete from cache", e);
}
}
protected getR2Key(key: string, cacheType?: CacheEntryType): string {
return computeCacheKey(key, {
prefix: getCloudflareContext().env[PREFIX_ENV_NAME],
buildId: process.env.NEXT_BUILD_ID,
cacheType,
});
}
}
export default new R2IncrementalCache();