From 3936bb7c855e29cdf4077a5a7a79871d6db73c94 Mon Sep 17 00:00:00 2001 From: zkldi Date: Wed, 15 May 2024 01:00:10 +0100 Subject: [PATCH] feat: update goals on folder change... (#1075) --- .../lib/score-import/framework/goals/goals.ts | 50 ++++++++++++++++++- server/src/scripts/sync-database.ts | 10 +++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/server/src/lib/score-import/framework/goals/goals.ts b/server/src/lib/score-import/framework/goals/goals.ts index c37466e55..d26197cf6 100644 --- a/server/src/lib/score-import/framework/goals/goals.ts +++ b/server/src/lib/score-import/framework/goals/goals.ts @@ -29,13 +29,18 @@ export async function UpdateGoalsForUser( goals: Array, goalSubsMap: Map, userID: integer, - logger: KtLogger + logger: KtLogger, + skipMismatch = false ) { const returns = await Promise.all( goals.map((goal: GoalDocument) => { const goalSub = goalSubsMap.get(goal.goalID); if (!goalSub) { + if (skipMismatch) { + return null; + } + logger.error( `UserGoal:GoalID mismatch ${goal.goalID} - this user has no goalSub for this, yet it is set.` ); @@ -49,7 +54,7 @@ export async function UpdateGoalsForUser( { goal, err, userID, goalSub } ); - return undefined; + return null; }); }) ); @@ -198,3 +203,44 @@ export async function ProcessGoal( webhookEvent, }; } + +export async function UpdateGoalsInFolder(folderID: string, logger: KtLogger) { + const goals = await db.goals.find({ + "charts.type": "folder", + "charts.data": folderID, + }); + + logger.info(`Updating ${goals.length} goals for ${folderID}`); + + const goalSubs = await db["goal-subs"].find({ + goalID: { $in: goals.map((e) => e.goalID) }, + }); + + logger.info(`Updating ${goalSubs.length} goal subs for ${folderID}`); + + // (User -> (goalID -> GoalSub)) + const ugsMap = new Map>(); + + for (const gSub of goalSubs) { + const userID = gSub.userID; + + if (ugsMap.has(userID)) { + ugsMap.get(userID)!.set(gSub.goalID, gSub); + } else { + ugsMap.set(userID, new Map()); + ugsMap.get(userID)!.set(gSub.goalID, gSub); + } + } + + const promises = []; + + for (const [userID, goalSubsMap] of ugsMap.entries()) { + promises.push(async () => { + // hack: pass *all* goals here to avoid mass allocations + // use `skipMismatch` to ignore the cases where they don't match + await UpdateGoalsForUser(goals, goalSubsMap, userID, logger, true); + }); + } + + await Promise.all(promises); +} diff --git a/server/src/scripts/sync-database.ts b/server/src/scripts/sync-database.ts index e7c5d7dce..f6f701d47 100644 --- a/server/src/scripts/sync-database.ts +++ b/server/src/scripts/sync-database.ts @@ -6,13 +6,15 @@ import db, { monkDB } from "external/mongo/db"; import fjsh from "fast-json-stable-hash"; import { PullDatabaseSeeds } from "lib/database-seeds/repo"; import CreateLogCtx from "lib/logger/logger"; +import { UpdateGoalsInFolder } from "lib/score-import/framework/goals/goals"; import UpdateIsPrimaryStatus from "lib/score-mutation/update-isprimary"; import { ServerConfig, TachiConfig } from "lib/setup/config"; import { RemoveStaleFolderShowcaseStats } from "lib/showcase/showcase"; +import { GetRelevantFolderGoals } from "lib/targets/goals"; import { UpdateQuestSubscriptions } from "lib/targets/quests"; import { RecalcAllScores } from "utils/calculations/recalc-scores"; import { UpdateGameSongIDCounter } from "utils/db"; -import { InitaliseFolderChartLookup } from "utils/folder"; +import { GetFolderChartIDs, InitaliseFolderChartLookup } from "utils/folder"; import { ArrayDiff, IsSupported, WrapScriptPromise } from "utils/misc"; import type { KtLogger } from "lib/logger/logger"; import type { BulkWriteOperation, DeleteWriteOpResultObject } from "mongodb"; @@ -265,6 +267,12 @@ const syncInstructions: Array = [ ); await RemoveStaleFolderShowcaseStats(removedFolderIDs); + + // update goals for everyone that was affected + + await Promise.all( + keptFolderIDs.map((f) => UpdateGoalsInFolder(f.folderID, logger)) + ); } }, },