Skip to content

Commit f60141f

Browse files
author
Nicolas Dorseuil
committed
create a cache key type
1 parent 456286b commit f60141f

File tree

9 files changed

+170
-148
lines changed

9 files changed

+170
-148
lines changed

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

Lines changed: 56 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
IncrementalCacheContext,
44
IncrementalCacheValue,
55
} from "types/cache";
6+
import type { CacheKey } from "types/overrides";
67
import {
78
createCacheKey,
89
getTagsFromValue,
@@ -63,8 +64,8 @@ export default class Cache {
6364
async getFetchCache(baseKey: string, softTags?: string[], tags?: string[]) {
6465
debug("get fetch cache", { baseKey, softTags, tags });
6566
try {
66-
const key = createCacheKey(baseKey, true);
67-
const cachedEntry = await globalThis.incrementalCache.get(key, "fetch");
67+
const key = createCacheKey({ key: baseKey, type: "fetch" });
68+
const cachedEntry = await globalThis.incrementalCache.get(key);
6869

6970
if (cachedEntry?.value === undefined) return null;
7071

@@ -116,8 +117,11 @@ export default class Cache {
116117
baseKey: string,
117118
): Promise<CacheHandlerValue | null> {
118119
try {
119-
const key = createCacheKey(baseKey, false);
120-
const cachedEntry = await globalThis.incrementalCache.get(key, "cache");
120+
const key = createCacheKey({
121+
key: baseKey,
122+
type: "cache",
123+
});
124+
const cachedEntry = await globalThis.incrementalCache.get(key);
121125

122126
if (!cachedEntry?.value) {
123127
return null;
@@ -208,7 +212,11 @@ export default class Cache {
208212
if (globalThis.openNextConfig.dangerous?.disableIncrementalCache) {
209213
return;
210214
}
211-
const key = createCacheKey(baseKey, data?.kind === "FETCH");
215+
const key = createCacheKey({
216+
key: baseKey,
217+
type: data?.kind === "FETCH" ? "fetch" : "cache",
218+
});
219+
debug("Setting cache", { key, data, ctx });
212220
// This one might not even be necessary anymore
213221
// Better be safe than sorry
214222
const detachedPromise = globalThis.__openNextAls
@@ -217,96 +225,76 @@ export default class Cache {
217225
try {
218226
if (data === null || data === undefined) {
219227
// only case where we delete the cache is for ISR/SSG cache
220-
await globalThis.incrementalCache.delete(key);
228+
await globalThis.incrementalCache.delete(key as CacheKey<"cache">);
221229
} else {
222230
const revalidate = this.extractRevalidateForSet(ctx);
223231
switch (data.kind) {
224232
case "ROUTE":
225233
case "APP_ROUTE": {
226234
const { body, status, headers } = data;
227-
await globalThis.incrementalCache.set(
228-
key,
229-
{
230-
type: "route",
231-
body: body.toString(
232-
isBinaryContentType(String(headers["content-type"]))
233-
? "base64"
234-
: "utf8",
235-
),
236-
meta: {
237-
status,
238-
headers,
239-
},
240-
revalidate,
235+
await globalThis.incrementalCache.set(key, {
236+
type: "route",
237+
body: body.toString(
238+
isBinaryContentType(String(headers["content-type"]))
239+
? "base64"
240+
: "utf8",
241+
),
242+
meta: {
243+
status,
244+
headers,
241245
},
242-
"cache",
243-
);
246+
revalidate,
247+
});
244248
break;
245249
}
246250
case "PAGE":
247251
case "PAGES": {
248252
const { html, pageData, status, headers } = data;
249253
const isAppPath = typeof pageData === "string";
250254
if (isAppPath) {
251-
await globalThis.incrementalCache.set(
252-
key,
253-
{
254-
type: "app",
255-
html,
256-
rsc: pageData,
257-
meta: {
258-
status,
259-
headers,
260-
},
261-
revalidate,
262-
},
263-
"cache",
264-
);
265-
} else {
266-
await globalThis.incrementalCache.set(
267-
key,
268-
{
269-
type: "page",
270-
html,
271-
json: pageData,
272-
revalidate,
273-
},
274-
"cache",
275-
);
276-
}
277-
break;
278-
}
279-
case "APP_PAGE": {
280-
const { html, rscData, headers, status } = data;
281-
await globalThis.incrementalCache.set(
282-
key,
283-
{
255+
await globalThis.incrementalCache.set(key, {
284256
type: "app",
285257
html,
286-
rsc: rscData.toString("utf8"),
258+
rsc: pageData,
287259
meta: {
288260
status,
289261
headers,
290262
},
291263
revalidate,
264+
});
265+
} else {
266+
await globalThis.incrementalCache.set(key, {
267+
type: "page",
268+
html,
269+
json: pageData,
270+
revalidate,
271+
});
272+
}
273+
break;
274+
}
275+
case "APP_PAGE": {
276+
const { html, rscData, headers, status } = data;
277+
await globalThis.incrementalCache.set(key, {
278+
type: "app",
279+
html,
280+
rsc: rscData.toString("utf8"),
281+
meta: {
282+
status,
283+
headers,
292284
},
293-
"cache",
294-
);
285+
revalidate,
286+
});
295287
break;
296288
}
297289
case "FETCH":
298-
await globalThis.incrementalCache.set(key, data, "fetch");
290+
await globalThis.incrementalCache.set(key, data);
299291
break;
300292
case "REDIRECT":
301-
await globalThis.incrementalCache.set(
302-
key,
303-
{
304-
type: "redirect",
305-
props: data.props,
306-
revalidate,
307-
},
308-
"cache",
309-
);
293+
await globalThis.incrementalCache.set(key, {
294+
type: "redirect",
295+
props: data.props,
296+
revalidate,
297+
});
310298
break;
311299
case "IMAGE":
312300
// Not implemented

packages/open-next/src/adapters/composable-cache.ts

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { ComposableCacheEntry, ComposableCacheHandler } from "types/cache";
2+
import type { CacheKey } from "types/overrides";
23
import { writeTags } from "utils/cache";
34
import { fromReadableStream, toReadableStream } from "utils/stream";
45
import { debug } from "./logger";
@@ -10,20 +11,25 @@ const pendingWritePromiseMap = new Map<string, Promise<ComposableCacheEntry>>();
1011
* @param key The composable cache key
1112
* @returns The composable cache key.
1213
*/
13-
function getComposableCacheKey(key: string): string {
14+
function getComposableCacheKey(key: string): CacheKey<"composable"> {
1415
try {
1516
const shouldPrependBuildId =
1617
globalThis.openNextConfig.dangerous?.persistentDataCache !== true;
17-
if (shouldPrependBuildId) {
18-
return key;
19-
}
2018
const [_buildId, ...rest] = JSON.parse(key);
21-
return JSON.stringify([...rest]);
19+
return {
20+
cacheType: "composable",
21+
buildId: shouldPrependBuildId ? _buildId : undefined,
22+
baseKey: JSON.stringify(rest),
23+
} as CacheKey<"composable">;
2224
} catch (e) {
2325
debug("Error while parsing composable cache key", e);
2426
// If we fail to parse the key, we just return it as is
2527
// This is not ideal, but we don't want to crash the application
26-
return key;
28+
return {
29+
cacheType: "composable",
30+
buildId: process.env.NEXT_BUILD_ID ?? "undefined-build-id",
31+
baseKey: key,
32+
};
2733
}
2834
}
2935

@@ -33,13 +39,10 @@ export default {
3339
const cacheKey = getComposableCacheKey(key);
3440
// We first check if we have a pending write for this cache key
3541
// If we do, we return the pending promise instead of fetching the cache
36-
if (pendingWritePromiseMap.has(cacheKey)) {
37-
return pendingWritePromiseMap.get(cacheKey);
42+
if (pendingWritePromiseMap.has(cacheKey.baseKey)) {
43+
return pendingWritePromiseMap.get(cacheKey.baseKey);
3844
}
39-
const result = await globalThis.incrementalCache.get(
40-
cacheKey,
41-
"composable",
42-
);
45+
const result = await globalThis.incrementalCache.get(cacheKey);
4346
if (!result?.value?.value) {
4447
return undefined;
4548
}
@@ -62,7 +65,7 @@ export default {
6265
) {
6366
const hasBeenRevalidated =
6467
(await globalThis.tagCache.getLastModified(
65-
cacheKey,
68+
cacheKey.baseKey,
6669
result.lastModified,
6770
)) === -1;
6871
if (hasBeenRevalidated) return undefined;
@@ -80,24 +83,22 @@ export default {
8083

8184
async set(key: string, pendingEntry: Promise<ComposableCacheEntry>) {
8285
const cacheKey = getComposableCacheKey(key);
83-
pendingWritePromiseMap.set(cacheKey, pendingEntry);
86+
pendingWritePromiseMap.set(cacheKey.baseKey, pendingEntry);
8487
const entry = await pendingEntry.finally(() => {
85-
pendingWritePromiseMap.delete(cacheKey);
88+
pendingWritePromiseMap.delete(cacheKey.baseKey);
8689
});
8790
const valueToStore = await fromReadableStream(entry.value);
88-
await globalThis.incrementalCache.set(
89-
cacheKey,
90-
{
91-
...entry,
92-
value: valueToStore,
93-
},
94-
"composable",
95-
);
91+
await globalThis.incrementalCache.set(cacheKey, {
92+
...entry,
93+
value: valueToStore,
94+
});
9695
if (globalThis.tagCache.mode === "original") {
97-
const storedTags = await globalThis.tagCache.getByPath(cacheKey);
96+
const storedTags = await globalThis.tagCache.getByPath(cacheKey.baseKey);
9897
const tagsToWrite = entry.tags.filter((tag) => !storedTags.includes(tag));
9998
if (tagsToWrite.length > 0) {
100-
await writeTags(tagsToWrite.map((tag) => ({ tag, path: cacheKey })));
99+
await writeTags(
100+
tagsToWrite.map((tag) => ({ tag, path: cacheKey.baseKey })),
101+
);
101102
}
102103
}
103104
},

packages/open-next/src/core/routing/cacheInterceptor.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import type { InternalEvent, InternalResult } from "types/open-next";
55
import type { CacheValue } from "types/overrides";
66
import { emptyReadableStream, toReadableStream } from "utils/stream";
77

8-
import { getTagsFromValue, hasBeenRevalidated } from "utils/cache";
8+
import {
9+
createCacheKey,
10+
getTagsFromValue,
11+
hasBeenRevalidated,
12+
} from "utils/cache";
913
import { debug } from "../../adapters/logger";
1014
import { localizePath } from "./i18n";
1115
import { generateMessageGroupId } from "./queue";
@@ -208,7 +212,10 @@ export async function cacheInterceptor(
208212
if (isISR) {
209213
try {
210214
const cachedData = await globalThis.incrementalCache.get(
211-
localizedPath ?? "/index",
215+
createCacheKey({
216+
key: localizedPath ?? "/index",
217+
type: "cache",
218+
}),
212219
);
213220
debug("cached data in interceptor", cachedData);
214221

packages/open-next/src/overrides/incrementalCache/fs-dev.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@ const getCacheKey = (key: string) => {
1212

1313
const cache: IncrementalCache = {
1414
name: "fs-dev",
15-
get: async (key: string) => {
16-
const fileData = await fs.readFile(getCacheKey(key), "utf-8");
15+
get: async ({ baseKey }) => {
16+
const fileData = await fs.readFile(getCacheKey(baseKey), "utf-8");
1717
const data = JSON.parse(fileData);
18-
const { mtime } = await fs.stat(getCacheKey(key));
18+
const { mtime } = await fs.stat(getCacheKey(baseKey));
1919
return {
2020
value: data,
2121
lastModified: mtime.getTime(),
2222
};
2323
},
24-
set: async (key, value, isFetch) => {
24+
set: async ({ baseKey }, value) => {
2525
const data = JSON.stringify(value);
26-
const cacheKey = getCacheKey(key);
26+
const cacheKey = getCacheKey(baseKey);
2727
// We need to create the directory before writing the file
2828
await fs.mkdir(path.dirname(cacheKey), { recursive: true });
2929
await fs.writeFile(cacheKey, data);
3030
},
31-
delete: async (key) => {
32-
await fs.rm(getCacheKey(key));
31+
delete: async ({ baseKey }) => {
32+
await fs.rm(getCacheKey(baseKey));
3333
},
3434
};
3535

0 commit comments

Comments
 (0)