Skip to content

Commit 8121659

Browse files
committed
basic implementation for composable cache
1 parent d453e0c commit 8121659

File tree

7 files changed

+120
-3
lines changed

7 files changed

+120
-3
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type {
2+
ComposableCacheEntry,
3+
ComposableCacheHandler,
4+
StoredComposableCacheEntry,
5+
} from "types/cache";
6+
import { fromReadableStream, toReadableStream } from "utils/stream";
7+
import { debug } from "./logger";
8+
9+
export default {
10+
async get(cacheKey: string) {
11+
try {
12+
// TODO: update the type of the incremental cache
13+
const result = (await globalThis.incrementalCache.get(
14+
cacheKey,
15+
true,
16+
)) as unknown as StoredComposableCacheEntry;
17+
18+
debug("composable cache result", result);
19+
20+
return {
21+
...result.value,
22+
value: toReadableStream(result.value.value),
23+
};
24+
} catch (e) {
25+
debug("Cannot read composable cache entry");
26+
return undefined;
27+
}
28+
},
29+
30+
async set(cacheKey: string, pendingEntry: Promise<ComposableCacheEntry>) {
31+
const entry = await pendingEntry;
32+
const valueToStore = await fromReadableStream(entry.value);
33+
await globalThis.incrementalCache.set(cacheKey, {
34+
...entry,
35+
value: valueToStore,
36+
} as any);
37+
},
38+
39+
async refreshTags() {
40+
// We don't do anything for now, do we want to do something here ???
41+
return;
42+
},
43+
async getExpiration(...tags: string[]) {
44+
if (globalThis.tagCache.mode === "nextMode") {
45+
return globalThis.tagCache.getLastRevalidated(tags);
46+
}
47+
//TODO: Not supported for now - I'll need to figure out a way, maybe we'd want to merge both type into one
48+
return 0;
49+
},
50+
async expireTags(...tags: string[]) {
51+
if (globalThis.tagCache.mode === "nextMode") {
52+
return globalThis.tagCache.writeTags(tags);
53+
}
54+
},
55+
} satisfies ComposableCacheHandler;

packages/open-next/src/build/compileCache.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,49 @@ export function compileCache(
1515
) {
1616
const { config } = options;
1717
const ext = format === "cjs" ? "cjs" : "mjs";
18-
const outFile = path.join(options.buildDir, `cache.${ext}`);
18+
const compiledCacheFile = path.join(options.buildDir, `cache.${ext}`);
19+
const compiledComposableCacheFile = path.join(
20+
options.buildDir,
21+
`composable-cache.${ext}`,
22+
);
1923

2024
const isAfter15 = buildHelper.compareSemver(
2125
options.nextVersion,
2226
">=",
2327
"15.0.0",
2428
);
2529

30+
// Normal cache
2631
buildHelper.esbuildSync(
2732
{
2833
external: ["next", "styled-jsx", "react", "@aws-sdk/*"],
2934
entryPoints: [path.join(options.openNextDistDir, "adapters", "cache.js")],
30-
outfile: outFile,
35+
outfile: compiledCacheFile,
36+
target: ["node18"],
37+
format,
38+
banner: {
39+
js: [
40+
`globalThis.disableIncrementalCache = ${
41+
config.dangerous?.disableIncrementalCache ?? false
42+
};`,
43+
`globalThis.disableDynamoDBCache = ${
44+
config.dangerous?.disableTagCache ?? false
45+
};`,
46+
`globalThis.isNextAfter15 = ${isAfter15};`,
47+
].join(""),
48+
},
49+
},
50+
options,
51+
);
52+
53+
// Composable cache
54+
buildHelper.esbuildSync(
55+
{
56+
external: ["next", "styled-jsx", "react", "@aws-sdk/*"],
57+
entryPoints: [
58+
path.join(options.openNextDistDir, "adapters", "composable-cache.js"),
59+
],
60+
outfile: compiledComposableCacheFile,
3161
target: ["node18"],
3262
format,
3363
banner: {
@@ -44,5 +74,9 @@ export function compileCache(
4474
},
4575
options,
4676
);
47-
return outFile;
77+
78+
return {
79+
cache: compiledCacheFile,
80+
composableCache: compiledComposableCacheFile,
81+
};
4882
}

packages/open-next/src/build/createServerBundle.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,16 @@ async function generateBundle(
147147
fs.mkdirSync(outPackagePath, { recursive: true });
148148

149149
const ext = fnOptions.runtime === "deno" ? "mjs" : "cjs";
150+
// Normal cache
150151
fs.copyFileSync(
151152
path.join(options.buildDir, `cache.${ext}`),
152153
path.join(outPackagePath, "cache.cjs"),
153154
);
155+
// Composable cache
156+
fs.copyFileSync(
157+
path.join(options.buildDir, `composable-cache.${ext}`),
158+
path.join(outPackagePath, "composable-cache.cjs"),
159+
);
154160

155161
if (fnOptions.runtime === "deno") {
156162
addDenoJson(outputPath, packagePath);
@@ -237,6 +243,12 @@ async function generateBundle(
237243
"14.2",
238244
);
239245

246+
const isAfter152 = buildHelper.compareSemver(
247+
options.nextVersion,
248+
">=",
249+
"15.2.0",
250+
);
251+
240252
const disableRouting = isBefore13413 || config.middleware?.external;
241253

242254
const updater = new ContentUpdater(options);
@@ -265,6 +277,7 @@ async function generateBundle(
265277
...(isAfter141
266278
? ["experimentalIncrementalCacheHandler"]
267279
: ["stableIncrementalCache"]),
280+
...(isAfter152 ? [] : ["composableCache"]),
268281
],
269282
}),
270283

packages/open-next/src/core/util.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ overrideNextjsRequireHooks(NextConfig);
2525
applyNextjsRequireHooksOverride();
2626
//#endOverride
2727
const cacheHandlerPath = require.resolve("./cache.cjs");
28+
const composableCacheHandlerPath = require.resolve("./composable-cache.cjs");
2829
// @ts-ignore
2930
const nextServer = new NextServer.default({
3031
//#override requestHandlerHost
@@ -52,6 +53,12 @@ const nextServer = new NextServer.default({
5253
//#override experimentalIncrementalCacheHandler
5354
incrementalCacheHandlerPath: cacheHandlerPath,
5455
//#endOverride
56+
57+
//#override composableCache
58+
cacheHandlers: {
59+
default: composableCacheHandlerPath,
60+
},
61+
//#endOverride
5562
},
5663
},
5764
customServer: false,

packages/open-next/src/overrides/tagCache/dynamodb-nextMode.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ function buildDynamoObject(tag: string, revalidatedAt?: number) {
7171
export default {
7272
name: "ddb-nextMode",
7373
mode: "nextMode",
74+
getLastRevalidated: async (tags: string[]) => {
75+
// Not supported for now
76+
return 0;
77+
},
7478
hasBeenRevalidated: async (tags: string[], lastModified?: number) => {
7579
if (globalThis.openNextConfig.dangerous?.disableTagCache) {
7680
return false;

packages/open-next/src/types/cache.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { ReadableStream } from "node:stream/web";
2+
13
interface CachedFetchValue {
24
kind: "FETCH";
35
data: {

packages/open-next/src/types/overrides.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ Cons :
129129
*/
130130
export type NextModeTagCache = BaseTagCache & {
131131
mode: "nextMode";
132+
// Necessary for the composable cache
133+
getLastRevalidated(tags: string[]): Promise<number>;
132134
hasBeenRevalidated(tags: string[], lastModified?: number): Promise<boolean>;
133135
writeTags(tags: string[]): Promise<void>;
134136
// Optional method to get paths by tags

0 commit comments

Comments
 (0)