Skip to content

Commit 8dbc790

Browse files
committed
feat: use native cache api
1 parent 64397bb commit 8dbc790

File tree

6 files changed

+46
-167
lines changed

6 files changed

+46
-167
lines changed

src/cloudflare-worker/cache.ts

Lines changed: 0 additions & 60 deletions
This file was deleted.

src/cloudflare-worker/handler.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Router } from "itty-router";
22
import { Config, Generator } from "../core";
3-
import { Cache } from "./cache";
43
import demo from "./demo";
54
import Header from "./headers";
65
import { sanitize } from "./sanitize";
@@ -25,17 +24,16 @@ async function generate(config: Record<string, string>, req: Request): Promise<R
2524
}
2625
console.log("sanitized config", JSON.stringify(sanitized, null, 4));
2726

28-
const cache_time = parseInt(config.cache || "60") ?? 60;
29-
const cache_header =
30-
`max-age=${cache_time}` + (cache_time <= 0 ? ", no-store, no-cache" : ", public");
27+
const cache_time = parseInt(config.cache || "300") ?? 300;
28+
const cache = await caches.open("leetcode");
3129

32-
const generator = new Generator(new Cache(cache_time), {
30+
const generator = new Generator(cache, {
3331
"user-agent": req.headers.get("user-agent") || "Unknown",
3432
});
3533
generator.verbose = true;
3634

3735
const headers = new Header().add("cors", "svg");
38-
headers.set("cache-control", cache_header);
36+
headers.set("cache-control", `public, max-age=${cache_time}`);
3937

4038
return new Response(await generator.generate(sanitized), { headers });
4139
}
@@ -57,18 +55,6 @@ router.get("*", async (req: { query: Record<string, string> }) => {
5755
return await generate(req.query, req as unknown as Request);
5856
});
5957

60-
router.delete("/:site/:username", async ({ params }) => {
61-
if (params?.site && params?.username) {
62-
const site = params.site.toLowerCase();
63-
const username = params.username.toLowerCase();
64-
const cache = new Cache(60);
65-
return new Response(
66-
JSON.stringify({ success: await cache.delete(`data-${username}-${site}`) }, null, 4),
67-
{ headers: new Header().add("cors", "json") },
68-
);
69-
}
70-
});
71-
7258
// 404 for all other routes
7359
router.all("*", () => new Response("Not Found.", { status: 404 }));
7460

src/core/cache.ts

Lines changed: 0 additions & 64 deletions
This file was deleted.

src/core/card.ts

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Icon, Ranking, Root, Solved, TotalSolved, Username } from "./elements";
22
import { Item } from "./item";
33
import query from "./query";
4-
import { Cache, Config, Extension, FetchedData } from "./types";
4+
import { Config, Extension, FetchedData } from "./types";
55

66
export class Generator {
77
public verbose = false;
@@ -13,11 +13,11 @@ export class Generator {
1313
css: [],
1414
extensions: [],
1515
};
16-
public cache: Cache;
16+
public cache?: Cache;
1717
public headers: Record<string, string>;
18-
public count = 0;
18+
public fetches: Record<string, Promise<FetchedData>> = {};
1919

20-
constructor(cache: Cache, headers?: Record<string, string>) {
20+
constructor(cache?: Cache, headers?: Record<string, string>) {
2121
this.cache = cache;
2222
this.headers = headers ?? {};
2323
}
@@ -38,7 +38,7 @@ export class Generator {
3838
const data = (async () => {
3939
const start = Date.now();
4040
const data = await this.fetch(config.username, config.site, this.headers);
41-
this.log(`user data fetched in ${Date.now() - start} ms`, data);
41+
this.log(`user data fetched in ${Date.now() - start} ms`, data.profile);
4242
return data;
4343
})();
4444
const body = this.body();
@@ -54,26 +54,56 @@ export class Generator {
5454
headers: Record<string, string>,
5555
): Promise<FetchedData> {
5656
this.log("fetching", username, site);
57-
const cache_key = `data-${username.toLowerCase()}-${site}`;
57+
const cache_key = `https://leetcode-stats-card.local/data-${username.toLowerCase()}-${site}`;
5858
console.log("cache_key", cache_key);
5959

60-
await new Promise((resolve) => setTimeout(resolve, 200 * (this.count++ % 5)));
61-
const cached: FetchedData | null = await this.cache.get(cache_key);
60+
if (cache_key in this.fetches) {
61+
return this.fetches[cache_key];
62+
}
63+
this.fetches[cache_key] = this._fetch(username, site, headers, cache_key);
64+
this.fetches[cache_key].finally(() => {
65+
delete this.fetches[cache_key];
66+
});
67+
return this.fetches[cache_key];
68+
}
69+
70+
protected async _fetch(
71+
username: string,
72+
site: "us" | "cn",
73+
headers: Record<string, string>,
74+
cache_key: string,
75+
): Promise<FetchedData> {
76+
this.log("fetching", username, site);
77+
const cached = await this.cache?.match(cache_key);
6278
if (cached) {
6379
this.log("fetch cache hit");
64-
return cached;
80+
return cached.json();
6581
} else {
6682
this.log("fetch cache miss");
6783
}
6884

6985
try {
7086
if (site === "us") {
7187
const data = await query.us(username, headers);
72-
this.cache.put(cache_key, data).catch(console.error);
88+
await this.cache
89+
?.put(
90+
cache_key,
91+
new Response(JSON.stringify(data), {
92+
headers: { "cache-control": "max-age=300" },
93+
}),
94+
)
95+
.catch(console.error);
7396
return data;
7497
} else {
7598
const data = await query.cn(username, headers);
76-
this.cache.put(cache_key, data).catch(console.error);
99+
await this.cache
100+
?.put(
101+
cache_key,
102+
new Response(JSON.stringify(data), {
103+
headers: { "cache-control": "max-age=300" },
104+
}),
105+
)
106+
.catch(console.error);
77107
return data;
78108
}
79109
} catch (err) {

src/core/index.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { MemoryCache } from "./cache";
21
import { Generator } from "./card";
32
import { ActivityExtension } from "./exts/activity";
43
import { AnimationExtension } from "./exts/animation";
@@ -9,18 +8,13 @@ import { RemoteStyleExtension } from "./exts/remote-style";
98
import { ThemeExtension } from "./exts/theme";
109
import { Config } from "./types";
1110

12-
/**
13-
* The default in-memory cache instance.
14-
*/
15-
export const cache = new MemoryCache();
16-
1711
/**
1812
* Generate a card.
1913
* @param config The configuration of the card
2014
* @returns The card (svg)
2115
*/
2216
export async function generate(config: Partial<Config>): Promise<string> {
23-
const generator = new Generator(cache);
17+
const generator = new Generator();
2418
return await generator.generate({
2519
username: "jacoblincool",
2620
site: "us",
@@ -44,7 +38,6 @@ export {
4438
FontExtension,
4539
Generator,
4640
HeatmapExtension,
47-
MemoryCache,
4841
RemoteStyleExtension,
4942
ThemeExtension,
5043
};

src/core/types.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { Generator } from "./card";
22

3-
export interface Cache {
4-
put: (key: string, value: unknown, options?: Record<string, unknown>) => Promise<void>;
5-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6-
get: (key: string) => Promise<any | null>;
7-
}
8-
93
export interface Config {
104
username: string;
115
site: "us" | "cn";

0 commit comments

Comments
 (0)