Skip to content

Commit 6ce3cea

Browse files
authored
Stop using KV cache backend for now, but also improves it for higher performances (#2510)
1 parent 250e77d commit 6ce3cea

File tree

3 files changed

+20
-72
lines changed

3 files changed

+20
-72
lines changed

.changeset/popular-toys-argue.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'gitbook': patch
3+
---
4+
5+
Stop using KV cache backend for now, but also improves it for higher performances
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { cloudflareCache } from './cloudflare-cache';
22
import { cloudflareDOCache } from './cloudflare-do';
3-
import { cloudflareKVCache } from './cloudflare-kv';
43
import { memoryCache } from './memory';
54

65
export const cacheBackends = [
@@ -10,7 +9,6 @@ export const cacheBackends = [
109
// Cache local to the datacenter
1110
// It can't be purged globally but it's faster
1211
cloudflareCache,
13-
// Cache global, but with slow replication
14-
cloudflareKVCache,
12+
// Global cache with slower performances
1513
cloudflareDOCache,
1614
];

packages/gitbook/src/lib/cache/cloudflare-kv.ts

Lines changed: 14 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,23 @@
11
import type { KVNamespace } from '@cloudflare/workers-types';
22

3-
import { CacheBackend, CacheEntry, CacheEntryMeta } from './types';
3+
import { CacheBackend, CacheEntry, CacheEntryLookup, CacheEntryMeta } from './types';
44
import { getCacheMaxAge } from './utils';
55
import { trace } from '../tracing';
66

7-
const cacheVersion = 1;
7+
const cacheVersion = 2;
88

99
interface KVTagMetadata {
1010
meta: CacheEntryMeta;
1111
}
1212

13-
/**
14-
* As we migrate off KV, we start disabling it for some tests content.
15-
*/
16-
const noKVTags = new Set([
17-
// docs.gitbook.com
18-
'url:docs.gitbook.com',
19-
'site:site_p4Xo4',
20-
'space:NkEGS7hzeqa35sMXQZ4X',
21-
]);
22-
23-
function shouldUseKVForTag(tag: string): boolean {
24-
if (noKVTags.has(tag)) {
25-
return false;
26-
}
27-
if (tag.startsWith('change-request:')) {
28-
return false;
29-
}
30-
31-
// Hash the tag and return true for 95% of the tags
32-
const hash = tag.split('').reduce((acc, char) => {
33-
return acc + char.charCodeAt(0);
34-
}, 0);
35-
if (hash % 100 <= 30) {
36-
return true;
37-
}
38-
39-
return false;
40-
}
41-
4213
/**
4314
* Cache implementation using the Cloudflare KV API.
4415
* https://developers.cloudflare.com/kv/
4516
*/
4617
export const cloudflareKVCache: CacheBackend = {
4718
name: 'cloudflare-kv',
4819
replication: 'global',
49-
async get({ key, tag }, options) {
50-
if (tag && !shouldUseKVForTag(tag)) {
51-
return null;
52-
}
53-
20+
async get(entry, options) {
5421
const kv = await getKVNamespace();
5522
if (!kv) {
5623
return null;
@@ -59,19 +26,19 @@ export const cloudflareKVCache: CacheBackend = {
5926
return trace(
6027
{
6128
operation: `cloudflareKV.get`,
62-
name: key,
29+
name: entry.key,
6330
},
6431
async (span) => {
65-
const kvKey = getValueKey(key);
32+
const kvKey = getKey(entry);
6633

67-
const entry = await kv.get<CacheEntry>(kvKey, {
34+
const kvEntry = await kv.get<CacheEntry>(kvKey, {
6835
type: 'json',
6936
cacheTtl: 60,
7037
});
7138

72-
span.setAttribute('hit', !!entry);
39+
span.setAttribute('hit', !!kvEntry);
7340

74-
return entry;
41+
return kvEntry;
7542
},
7643
);
7744
},
@@ -94,23 +61,10 @@ export const cloudflareKVCache: CacheBackend = {
9461
return;
9562
}
9663

97-
const kvKey = getValueKey(entry.meta.key);
64+
const kvKey = getKey(entry.meta);
9865
await kv.put(kvKey, JSON.stringify(entry), {
9966
expirationTtl: secondsFromNow,
10067
});
101-
102-
if (entry.meta.tag) {
103-
const metadata: KVTagMetadata = {
104-
meta: entry.meta,
105-
};
106-
const jsonMetadata = JSON.stringify(metadata);
107-
const tagKey = getTagKey(entry.meta.tag, entry.meta.key);
108-
109-
await kv.put(tagKey, jsonMetadata, {
110-
metadata,
111-
expirationTtl: secondsFromNow,
112-
});
113-
}
11468
},
11569
);
11670
},
@@ -121,8 +75,8 @@ export const cloudflareKVCache: CacheBackend = {
12175
}
12276

12377
await Promise.all(
124-
entries.map(async ({ key }) => {
125-
const kvKey = getValueKey(key);
78+
entries.map(async (entry) => {
79+
const kvKey = getKey(entry);
12680
await kv.delete(kvKey);
12781
}),
12882
);
@@ -147,12 +101,7 @@ export const cloudflareKVCache: CacheBackend = {
147101
for (const entry of entries.keys) {
148102
if (entry.metadata) {
149103
const metadata = entry.metadata;
150-
const key = metadata.meta.key;
151-
152104
result.push(metadata.meta);
153-
154-
// Delete the tag key and the value key
155-
pendingDeletions.push(kv.delete(getValueKey(key)));
156105
pendingDeletions.push(kv.delete(entry.name));
157106
}
158107
}
@@ -174,16 +123,12 @@ export const cloudflareKVCache: CacheBackend = {
174123
},
175124
};
176125

177-
function getValueKey(key: string): string {
178-
return `${cacheVersion}.v.${key}`;
126+
function getKey(entry: CacheEntryLookup) {
127+
return `${getTagPrefix(entry.tag || 'default')}.${entry.key}`;
179128
}
180129

181130
function getTagPrefix(tag: string) {
182-
return `${cacheVersion}.tag.${tag}.`;
183-
}
184-
185-
function getTagKey(tag: string, key: string) {
186-
return `${getTagPrefix(tag)}${key}`;
131+
return `${cacheVersion}.${tag}.`;
187132
}
188133

189134
async function getKVNamespace(): Promise<KVNamespace | null> {

0 commit comments

Comments
 (0)