Skip to content

Commit f2d73ea

Browse files
Merge branch 'master' of https://github.com/LuckySilver0021/caches-user-data into pr/7415
2 parents fb11861 + df7684c commit f2d73ea

File tree

6 files changed

+129
-155
lines changed

6 files changed

+129
-155
lines changed

backend/src/api/controllers/result.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import { MonkeyRequest } from "../types";
6464
import { getFunbox, checkCompatibility } from "@monkeytype/funbox";
6565
import { tryCatch } from "@monkeytype/util/trycatch";
6666
import { getCachedConfiguration } from "../../init/configuration";
67+
import { allTimeLeaderboardCache } from "../../utils/all-time-leaderboard-cache";
6768

6869
try {
6970
if (!anticheatImplemented()) throw new Error("undefined");
@@ -534,6 +535,13 @@ export async function addResult(
534535
},
535536
dailyLeaderboardsConfig,
536537
);
538+
try {
539+
allTimeLeaderboardCache.clear();
540+
console.log("All-time leaderboard cache cleared");
541+
} catch (error) {
542+
console.warn("Cache clear failed (non-critical):", error);
543+
}
544+
537545
if (
538546
dailyLeaderboardRank >= 1 &&
539547
dailyLeaderboardRank <= 10 &&

backend/src/credentials/.gitkeep

Whitespace-only changes.

backend/src/dal/leaderboards.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { DBUser, getUsersCollection } from "./user";
1515
import MonkeyError from "../utils/error";
1616
import { aggregateWithAcceptedConnections } from "./connections";
1717

18+
import { allTimeLeaderboardCache } from "../utils/all-time-leaderboard-cache";
19+
1820
export type DBLeaderboardEntry = LeaderboardEntry & {
1921
_id: ObjectId;
2022
};
@@ -46,6 +48,14 @@ export async function get(
4648
throw new MonkeyError(500, "Invalid page or pageSize");
4749
}
4850

51+
if (page === 0 && pageSize === 50 && uid === undefined) {
52+
const cached = allTimeLeaderboardCache.get({ mode, language });
53+
if (cached) {
54+
console.log("✅ Cache HIT - leaderboards");
55+
return cached.data as DBLeaderboardEntry[];
56+
}
57+
}
58+
4959
const skip = page * pageSize;
5060
const limit = pageSize;
5161

@@ -83,12 +93,23 @@ export async function get(
8393
leaderboard = leaderboard.map((it) => omit(it, ["isPremium"]));
8494
}
8595

96+
if (page === 0 && pageSize === 50 && uid === undefined) {
97+
try {
98+
allTimeLeaderboardCache.set(
99+
{ mode, language },
100+
leaderboard,
101+
await getCount(mode, mode2, language),
102+
);
103+
console.log(" Cache SET - leaderboards");
104+
} catch (error) {
105+
console.warn("Cache set failed:", error);
106+
}
107+
}
108+
86109
return leaderboard;
87110
} catch (e) {
88-
// oxlint-disable-next-line no-unsafe-member-access
89-
if (e.error === 175) {
111+
if ((e as unknown as { error: number }).error === 175) {
90112
//QueryPlanKilled, collection was removed during the query
91-
return false;
92113
}
93114
throw e;
94115
}
@@ -162,10 +183,8 @@ export async function getRank(
162183
return results[0] ?? null;
163184
}
164185
} catch (e) {
165-
// oxlint-disable-next-line no-unsafe-member-access
166-
if (e.error === 175) {
186+
if ((e as unknown as { error: number }).error === 175) {
167187
//QueryPlanKilled, collection was removed during the query
168-
return false;
169188
}
170189
throw e;
171190
}
@@ -393,8 +412,8 @@ async function createIndex(
393412
Logger.warning(`Index ${key} not matching, dropping and recreating...`);
394413

395414
const existingIndex = (await getUsersCollection().listIndexes().toArray())
396-
// oxlint-disable-next-line no-unsafe-member-access
397-
.map((it) => it.name as string)
415+
416+
.map((it: unknown) => (it as { name: string }).name)
398417
.find((it) => it.startsWith(key));
399418

400419
if (existingIndex !== undefined && existingIndex !== null) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
type AllTimeCacheKey = {
2+
mode: string;
3+
language: string;
4+
};
5+
6+
type CacheEntry = {
7+
data: unknown[];
8+
count: number;
9+
timestamp: number;
10+
};
11+
12+
class AllTimeLeaderboardCache {
13+
private cache = new Map<string, CacheEntry>();
14+
private readonly TTL = 900_000; // == 15 minutes of TTL
15+
16+
private getKey({ mode, language }: AllTimeCacheKey): string {
17+
return `alltime-lb:${mode}:${language}`;
18+
}
19+
20+
get(key: AllTimeCacheKey): CacheEntry | null {
21+
const cacheKey = this.getKey(key);
22+
const entry = this.cache.get(cacheKey);
23+
24+
if (!entry || Date.now() - entry.timestamp > this.TTL) {
25+
if (entry) this.cache.delete(cacheKey);
26+
return null;
27+
}
28+
return entry;
29+
}
30+
31+
set(key: AllTimeCacheKey, data: unknown[], count: number): void {
32+
this.cache.set(this.getKey(key), { data, count, timestamp: Date.now() });
33+
}
34+
35+
clear(): void {
36+
this.cache.clear();
37+
}
38+
}
39+
40+
export const allTimeLeaderboardCache = new AllTimeLeaderboardCache();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
"oxlint": "1.40.0",
7070
"oxlint-tsgolint": "0.11.1",
7171
"prettier": "3.7.1",
72-
"turbo": "2.5.6",
72+
"turbo": "2.7.5",
7373
"vitest": "4.0.15"
7474
},
7575
"lint-staged": {

0 commit comments

Comments
 (0)