Cache requests for blob and tree objects

This commit is contained in:
Thomas Scholtes
2024-02-28 10:59:06 +01:00
parent eb0013ef9c
commit 7ba9429afb
3 changed files with 34 additions and 2 deletions
+24 -2
View File
@@ -1,3 +1,4 @@
import { LRUCache } from "lru-cache";
import type { Commit, Commits } from "./project/commit.js"; import type { Commit, Commits } from "./project/commit.js";
import type { Embed } from "./project/comment.js"; import type { Embed } from "./project/comment.js";
import type { Fetcher, RequestOptions } from "./fetcher.js"; import type { Fetcher, RequestOptions } from "./fetcher.js";
@@ -142,6 +143,13 @@ const diffResponseSchema = object({
export class Client { export class Client {
#fetcher: Fetcher; #fetcher: Fetcher;
// We make the cache a static variable because clients are usually not
// persisted and new instances are frequently created.
static #cache = {
tree: new LRUCache<string, Tree>({ max: 300 }),
blob: new LRUCache<string, Blob>({ max: 500 }),
};
public constructor(fetcher: Fetcher) { public constructor(fetcher: Fetcher) {
this.#fetcher = fetcher; this.#fetcher = fetcher;
} }
@@ -221,7 +229,12 @@ export class Client {
path: string, path: string,
options?: RequestOptions, options?: RequestOptions,
): Promise<Blob> { ): Promise<Blob> {
return this.#fetcher.fetchOk( const cacheKey = `blob:${sha}:${path}`;
const cachedBlob = Client.#cache.blob.get(cacheKey);
if (cachedBlob) {
return cachedBlob;
}
const blob = await this.#fetcher.fetchOk(
{ {
method: "GET", method: "GET",
path: `projects/${id}/blob/${sha}/${path}`, path: `projects/${id}/blob/${sha}/${path}`,
@@ -229,6 +242,8 @@ export class Client {
}, },
blobSchema, blobSchema,
); );
Client.#cache.blob.set(cacheKey, blob);
return blob;
} }
public async getTree( public async getTree(
@@ -237,7 +252,12 @@ export class Client {
path?: string, path?: string,
options?: RequestOptions, options?: RequestOptions,
): Promise<Tree> { ): Promise<Tree> {
return this.#fetcher.fetchOk( const cacheKey = `tree:${sha}:${path}`;
const cachedTree = Client.#cache.tree.get(cacheKey);
if (cachedTree) {
return cachedTree;
}
const tree = await this.#fetcher.fetchOk(
{ {
method: "GET", method: "GET",
path: `projects/${id}/tree/${sha}/${path ?? ""}`, path: `projects/${id}/tree/${sha}/${path ?? ""}`,
@@ -245,6 +265,8 @@ export class Client {
}, },
treeSchema, treeSchema,
); );
Client.#cache.tree.set(cacheKey, tree);
return tree;
} }
public async getAllRemotes( public async getAllRemotes(
+9
View File
@@ -19,6 +19,7 @@
"hast-util-to-dom": "^4.0.0", "hast-util-to-dom": "^4.0.0",
"hast-util-to-html": "^9.0.0", "hast-util-to-html": "^9.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lru-cache": "^10.2.0",
"marked": "^11.1.1", "marked": "^11.1.1",
"marked-katex-extension": "^5.0.0", "marked-katex-extension": "^5.0.0",
"marked-linkify-it": "^3.1.8", "marked-linkify-it": "^3.1.8",
@@ -3303,6 +3304,14 @@
"get-func-name": "^2.0.1" "get-func-name": "^2.0.1"
} }
}, },
"node_modules/lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"engines": {
"node": "14 || >=16.14"
}
},
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.5", "version": "0.30.5",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
+1
View File
@@ -60,6 +60,7 @@
"hast-util-to-dom": "^4.0.0", "hast-util-to-dom": "^4.0.0",
"hast-util-to-html": "^9.0.0", "hast-util-to-html": "^9.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lru-cache": "^10.2.0",
"marked": "^11.1.1", "marked": "^11.1.1",
"marked-katex-extension": "^5.0.0", "marked-katex-extension": "^5.0.0",
"marked-linkify-it": "^3.1.8", "marked-linkify-it": "^3.1.8",