Skip to content

Commit b7b2eb8

Browse files
committed
Respond with all tags of all cache used for page generation
1 parent 9b5f971 commit b7b2eb8

File tree

6 files changed

+61
-6
lines changed

6 files changed

+61
-6
lines changed

packages/gitbook/src/cloudflare-entrypoint.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @ts-ignore
22
import nextOnPagesHandler from '@cloudflare/next-on-pages/fetch-handler';
33

4+
import { withResponseCacheTags } from './lib/cache';
45
import { withMiddlewareHeadersStorage } from './lib/middleware';
56

67
/**
@@ -9,8 +10,8 @@ import { withMiddlewareHeadersStorage } from './lib/middleware';
910
*/
1011
export default {
1112
async fetch(request, env, ctx) {
12-
const response = await withMiddlewareHeadersStorage(() =>
13-
nextOnPagesHandler.fetch(request, env, ctx)
13+
const response = await withResponseCacheTags(() =>
14+
withMiddlewareHeadersStorage(() => nextOnPagesHandler.fetch(request, env, ctx))
1415
);
1516

1617
return response;

packages/gitbook/src/lib/cache/cache.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { assertIsNotV2 } from '../v2';
77
import { waitUntil } from '../waitUntil';
88
import { cacheBackends } from './backends';
99
import { memoryCache } from './memory';
10+
import { addResponseCacheTag } from './response';
1011
import type { CacheBackend, CacheEntry } from './types';
1112

1213
export type CacheFunctionOptions = {
@@ -134,6 +135,11 @@ export function cache<Args extends any[], Result>(
134135
let result: readonly [CacheEntry, string] | null = null;
135136
const tag = cacheDef.tag?.(...args);
136137

138+
// Add the cache tag to the HTTP response
139+
if (tag) {
140+
addResponseCacheTag(tag);
141+
}
142+
137143
// Try the memory backend, independently of the other backends as it doesn't have a network cost
138144
const memoryEntry = await memoryCache.get({ key, tag });
139145
if (memoryEntry) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './cache';
22
export * from './http';
33
export * from './revalidateTags';
4+
export * from './response';
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { AsyncLocalStorage } from 'node:async_hooks';
2+
3+
const symbolResponseCacheTagsLocalStorage = Symbol.for('__gitbook-response-cache-tags__');
4+
5+
/**
6+
* Wrap a response handler with a storage to store cache tags and write them as header to the response.
7+
*/
8+
export async function withResponseCacheTags(handler: () => Promise<Response>): Promise<Response> {
9+
const responseCacheTagsLocalStorage =
10+
// @ts-ignore
11+
(globalThis[symbolResponseCacheTagsLocalStorage] as AsyncLocalStorage<Set<string>>) ??
12+
new AsyncLocalStorage<Set<string>>();
13+
// @ts-ignore
14+
globalThis[symbolResponseCacheTagsLocalStorage] = responseCacheTagsLocalStorage;
15+
16+
const responseCacheTags = new Set<string>();
17+
const response = await responseCacheTagsLocalStorage.run(responseCacheTags, handler);
18+
19+
if (responseCacheTags.size > 0) {
20+
const headerCacheTag = Array.from(responseCacheTags).join(',');
21+
response.headers.set('cache-tag', headerCacheTag);
22+
response.headers.set('x-gitbook-cache-tag', headerCacheTag);
23+
}
24+
25+
return response;
26+
}
27+
28+
/**
29+
* Add a cache tag to the HTTP response.
30+
* This is a hack for v1, for v2, we use ISR and do not cache the whole response.
31+
*/
32+
export function addResponseCacheTag(...tags: string[]) {
33+
const responseCacheTagsLocalStorage =
34+
// @ts-ignore
35+
(globalThis[symbolResponseCacheTagsLocalStorage] as AsyncLocalStorage<Set<string>>) ??
36+
new AsyncLocalStorage<Set<string>>();
37+
// @ts-ignore
38+
globalThis[symbolResponseCacheTagsLocalStorage] = responseCacheTagsLocalStorage;
39+
40+
const store = responseCacheTagsLocalStorage.getStore();
41+
tags.forEach((tag) => {
42+
store?.add(tag);
43+
});
44+
}

packages/gitbook/src/lib/middleware.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { AsyncLocalStorage } from 'node:async_hooks';
22

3+
/*
4+
* This code is ONLY for v1.
5+
*/
6+
37
/**
48
* Set a header on the middleware response.
59
* We do this because of https://github.com/opennextjs/opennextjs-cloudflare/issues/92

packages/gitbook/src/middleware.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
import { joinPath, normalizePathname } from '@/lib/paths';
3434
import { getProxyModeBasePath } from '@/lib/proxy';
3535
import { MiddlewareHeaders } from '@v2/lib/middleware';
36+
import { addResponseCacheTag } from './lib/cache';
3637

3738
export const config = {
3839
matcher:
@@ -287,10 +288,8 @@ export async function middleware(request: NextRequest) {
287288
}
288289
}
289290

290-
if (resolved.cacheTags && resolved.cacheTags.length > 0) {
291-
const headerCacheTag = resolved.cacheTags.join(',');
292-
setMiddlewareHeader(response, 'cache-tag', headerCacheTag);
293-
setMiddlewareHeader(response, 'x-gitbook-cache-tag', headerCacheTag);
291+
if (resolved.cacheTags) {
292+
addResponseCacheTag(...resolved.cacheTags);
294293
}
295294

296295
return response;

0 commit comments

Comments
 (0)