Skip to content

Commit 2b6c50c

Browse files
authored
perf: use local cache for configurations and psas (@fehmer) (#7429)
Endpoints /configurations and /psas are called very often but rarely change. Introduce a local cache for both of them. - cache configuration for 10 minutes. This was already in place but the endpoint always fetched the live configuration - cache psas for one minute
1 parent 1be66e6 commit 2b6c50c

3 files changed

Lines changed: 36 additions & 3 deletions

File tree

backend/src/api/controllers/configuration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { MonkeyRequest } from "../types";
1212
export async function getConfiguration(
1313
_req: MonkeyRequest,
1414
): Promise<GetConfigurationResponse> {
15-
const currentConfiguration = await Configuration.getLiveConfiguration();
15+
const currentConfiguration = await Configuration.getCachedConfiguration(true);
1616
return new MonkeyResponse("Configuration retrieved", currentConfiguration);
1717
}
1818

backend/src/api/controllers/psa.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@ import * as PsaDAL from "../../dal/psa";
33
import { MonkeyResponse } from "../../utils/monkey-response";
44
import { replaceObjectIds } from "../../utils/misc";
55
import { MonkeyRequest } from "../types";
6+
import { PSA } from "@monkeytype/schemas/psas";
7+
import { cacheWithTTL } from "../../utils/ttl-cache";
8+
9+
//cache for one minute
10+
const cache = cacheWithTTL<PSA[]>(1 * 60 * 1000, async () => {
11+
return replaceObjectIds(await PsaDAL.get());
12+
});
613

714
export async function getPsas(_req: MonkeyRequest): Promise<GetPsaResponse> {
8-
const data = await PsaDAL.get();
9-
return new MonkeyResponse("PSAs retrieved", replaceObjectIds(data));
15+
return new MonkeyResponse("PSAs retrieved", (await cache()) ?? []);
1016
}

backend/src/utils/ttl-cache.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Creates a caching function that loads data with a specified TTL (Time-to-Live).
3+
* If the cache has expired (based on TTL), it will re-fetch the data by calling the provided function.
4+
* Otherwise, it returns the cached value.
5+
*
6+
* @template T - The type of the value being cached.
7+
*
8+
* @param {number} ttlMs - The Time-to-Live (TTL) in milliseconds. The cache will refetch on call after this duration.
9+
* @param {() => Promise<T>} fn - A function that returns a promise resolving to the data to cache.
10+
*
11+
* @returns {() => Promise<T | undefined>}
12+
*/
13+
export function cacheWithTTL<T>(
14+
ttlMs: number,
15+
fn: () => Promise<T>,
16+
): () => Promise<T | undefined> {
17+
let lastFetchTime = 0;
18+
let cache: T | undefined;
19+
20+
return async () => {
21+
if (lastFetchTime < Date.now() - ttlMs) {
22+
lastFetchTime = Date.now();
23+
cache = await fn();
24+
}
25+
return cache;
26+
};
27+
}

0 commit comments

Comments
 (0)