perf(leaderboards): better index and aggregation code (fehmer) (#4836)

* perf: Improve leaderboard performance by adding better index

* review comments

* Allow aggregation to use disk if needed
This commit is contained in:
Christian Fehmer 2023-12-05 14:42:14 +01:00 committed by GitHub
parent bb2711e21e
commit 050cb7ab8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 19 deletions

View file

@ -72,25 +72,6 @@ export async function update(
.collection<MonkeyTypes.User>("users")
.aggregate<MonkeyTypes.LeaderboardEntry>(
[
{
$project: {
_id: 0,
[`${key}.wpm`]: 1,
[`${key}.acc`]: 1,
[`${key}.raw`]: 1,
[`${key}.consistency`]: 1,
[`${key}.timestamp`]: 1,
banned: 1,
lbOptOut: 1,
needsToChangeName: 1,
timeTyping: 1,
uid: 1,
name: 1,
discordId: 1,
discordAvatar: 1,
inventory: 1,
},
},
{
$match: {
[`${key}.wpm`]: {
@ -123,6 +104,25 @@ export async function update(
[`${key}.timestamp`]: -1,
},
},
{
$project: {
_id: 0,
[`${key}.wpm`]: 1,
[`${key}.acc`]: 1,
[`${key}.raw`]: 1,
[`${key}.consistency`]: 1,
[`${key}.timestamp`]: 1,
banned: 1,
lbOptOut: 1,
needsToChangeName: 1,
timeTyping: 1,
uid: 1,
name: 1,
discordId: 1,
discordAvatar: 1,
inventory: 1,
},
},
{
$set: {
[`${key}.uid`]: "$uid",
@ -234,3 +234,38 @@ export async function update(
};
}
}
async function createIndex(key: string): Promise<void> {
const index = {
[`${key}.wpm`]: -1,
[`${key}.acc`]: -1,
[`${key}.timestamp`]: -1,
[`${key}.raw`]: -1,
[`${key}.consistency`]: -1,
banned: 1,
lbOptOut: 1,
needsToChangeName: 1,
timeTyping: 1,
uid: 1,
name: 1,
discordId: 1,
discordAvatar: 1,
inventory: 1,
};
const partial = {
partialFilterExpression: {
[`${key}.wpm`]: {
$gt: 0,
},
timeTyping: {
$gt: isDevEnvironment() ? 0 : 7200,
},
},
};
await db.collection("users").createIndex(index, partial);
}
export async function createIndicies(): Promise<void> {
await createIndex("lbPersonalBests.time.15.english");
await createIndex("lbPersonalBests.time.60.english");
}

View file

@ -13,6 +13,8 @@ import Logger from "./utils/logger";
import * as EmailClient from "./init/email-client";
import { init as initFirebaseAdmin } from "./init/firebase-admin";
import { createIndicies as leaderboardDbSetup } from "./dal/leaderboards";
async function bootServer(port: number): Promise<Server> {
try {
Logger.info(`Starting server version ${version}`);
@ -63,6 +65,9 @@ async function bootServer(port: number): Promise<Server> {
jobs.forEach((job) => job.start());
Logger.success("Cron jobs started");
Logger.info("Setting up leaderboard indicies...");
await leaderboardDbSetup();
recordServerVersion(version);
} catch (error) {
Logger.error("Failed to boot server");