Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions backend/src/api/controllers/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import { MonkeyRequest } from "../types";
import { getFunbox, checkCompatibility } from "@monkeytype/funbox";
import { tryCatch } from "@monkeytype/util/trycatch";
import { getCachedConfiguration } from "../../init/configuration";
import { allTimeLeaderboardCache } from "../../utils/all-time-leaderboard-cache";

try {
if (!anticheatImplemented()) throw new Error("undefined");
Expand Down Expand Up @@ -534,6 +535,13 @@ export async function addResult(
},
dailyLeaderboardsConfig,
);
try {
allTimeLeaderboardCache.clear();
console.log("All-time leaderboard cache cleared");
} catch (error) {
console.warn("Cache clear failed (non-critical):", error);
}

if (
dailyLeaderboardRank >= 1 &&
dailyLeaderboardRank <= 10 &&
Expand Down
Empty file removed backend/src/credentials/.gitkeep
Empty file.
35 changes: 27 additions & 8 deletions backend/src/dal/leaderboards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { DBUser, getUsersCollection } from "./user";
import MonkeyError from "../utils/error";
import { aggregateWithAcceptedConnections } from "./connections";

import { allTimeLeaderboardCache } from "../utils/all-time-leaderboard-cache";

export type DBLeaderboardEntry = LeaderboardEntry & {
_id: ObjectId;
};
Expand Down Expand Up @@ -46,6 +48,14 @@ export async function get(
throw new MonkeyError(500, "Invalid page or pageSize");
}

if (page === 0 && pageSize === 50 && uid === undefined) {
const cached = allTimeLeaderboardCache.get({ mode, language });
if (cached) {
console.log("✅ Cache HIT - leaderboards");
return cached.data as DBLeaderboardEntry[];
}
}

const skip = page * pageSize;
const limit = pageSize;

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

if (page === 0 && pageSize === 50 && uid === undefined) {
try {
allTimeLeaderboardCache.set(
{ mode, language },
leaderboard,
await getCount(mode, mode2, language),
);
console.log(" Cache SET - leaderboards");
} catch (error) {
console.warn("Cache set failed:", error);
}
}

return leaderboard;
} catch (e) {
// oxlint-disable-next-line no-unsafe-member-access
if (e.error === 175) {
if ((e as unknown as { error: number }).error === 175) {
//QueryPlanKilled, collection was removed during the query
return false;
}
throw e;
}
Expand Down Expand Up @@ -162,10 +183,8 @@ export async function getRank(
return results[0] ?? null;
}
} catch (e) {
// oxlint-disable-next-line no-unsafe-member-access
if (e.error === 175) {
if ((e as unknown as { error: number }).error === 175) {
//QueryPlanKilled, collection was removed during the query
return false;
}
throw e;
}
Expand Down Expand Up @@ -393,8 +412,8 @@ async function createIndex(
Logger.warning(`Index ${key} not matching, dropping and recreating...`);

const existingIndex = (await getUsersCollection().listIndexes().toArray())
// oxlint-disable-next-line no-unsafe-member-access
.map((it) => it.name as string)

.map((it: unknown) => (it as { name: string }).name)
.find((it) => it.startsWith(key));

if (existingIndex !== undefined && existingIndex !== null) {
Expand Down
40 changes: 40 additions & 0 deletions backend/src/utils/all-time-leaderboard-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
type AllTimeCacheKey = {
mode: string;
language: string;
};

type CacheEntry = {
data: unknown[];
count: number;
timestamp: number;
};

class AllTimeLeaderboardCache {
private cache = new Map<string, CacheEntry>();
private readonly TTL = 900_000; // == 15 minutes of TTL

private getKey({ mode, language }: AllTimeCacheKey): string {
return `alltime-lb:${mode}:${language}`;
}

get(key: AllTimeCacheKey): CacheEntry | null {
const cacheKey = this.getKey(key);
const entry = this.cache.get(cacheKey);

if (!entry || Date.now() - entry.timestamp > this.TTL) {
if (entry) this.cache.delete(cacheKey);
return null;
}
return entry;
}

set(key: AllTimeCacheKey, data: unknown[], count: number): void {
this.cache.set(this.getKey(key), { data, count, timestamp: Date.now() });
}

clear(): void {
this.cache.clear();
}
}

export const allTimeLeaderboardCache = new AllTimeLeaderboardCache();
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"oxlint": "1.40.0",
"oxlint-tsgolint": "0.11.1",
"prettier": "3.7.1",
"turbo": "2.5.6",
"turbo": "2.7.5",
"vitest": "4.0.15"
},
"lint-staged": {
Expand Down
Loading
Loading