Skip to content

Commit c8083f1

Browse files
committed
feat(cache): TTL
1 parent 6cce984 commit c8083f1

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

src/lib/cache.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,43 @@
11
import fs from "node:fs/promises";
22
import path from "node:path";
33
import { fileURLToPath } from "node:url";
4-
import type { Schema } from "astro/zod";
4+
import { type Schema, z } from "zod";
5+
6+
// 1 week
7+
const DEFAULT_TTL = 7 * 24 * 60 * 60;
8+
const Meta = z.object({
9+
writtenAt: z.number(),
10+
});
11+
type Meta = z.infer<typeof Meta>;
512
/**
613
- this uses FS to cache. only use this for expensive things that need FS caching (such as fetching from the Internet)
714
- this does not cache `null` or `undefined`.
815
*/
916
export async function cache<T>(
1017
key: string,
11-
schema: Schema<T>,
18+
Schema: Schema<T>,
1219
load: () => Promise<T>,
20+
/** ttl: time-to-live in seconds */
21+
options: {
22+
ttl?: number;
23+
} = {},
1324
): Promise<T> {
25+
const ttl = options.ttl ?? DEFAULT_TTL;
26+
const now = new Date().getTime() / 1000;
1427
const path = await toPath(sanitizeKey(key));
1528

1629
// cache load
1730
if (await exists(path)) {
1831
try {
19-
const file = await fs.readFile(path, {
20-
encoding: "utf8",
21-
});
22-
const val = schema.parse(JSON.parse(file));
32+
const file = JSON.parse(
33+
await fs.readFile(path, {
34+
encoding: "utf8",
35+
}),
36+
);
37+
const data = Schema.parse(file.data);
38+
const meta = Meta.parse(file.meta);
2339
// cache hit
24-
return val;
40+
if (now - meta.writtenAt <= ttl) return data;
2541
} catch (err) {
2642
console.warn("failed to parse retrieved cache:", err);
2743
}
@@ -30,11 +46,17 @@ export async function cache<T>(
3046
// cache miss
3147
const val = await load();
3248

33-
const parse = schema.safeParse(val);
49+
const parse = Schema.safeParse(val);
3450
if (parse.success) {
3551
if (val != null) {
3652
// write cache
37-
await fs.writeFile(path, JSON.stringify(val));
53+
const content = {
54+
data: val,
55+
meta: {
56+
writtenAt: now,
57+
} satisfies Meta,
58+
};
59+
await fs.writeFile(path, JSON.stringify(content));
3860
}
3961
} else {
4062
// skip lcache

0 commit comments

Comments
 (0)