tidy up and document importing

This commit is contained in:
zkldi
2021-05-02 22:28:07 +01:00
parent 8d5e08d268
commit cded8d0dac
3 changed files with 52 additions and 32 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ import {
GoalDocument,
IIDXBPIData,
IIDXEamusementScoreDocument,
ImportDocument,
KTBlackImportDocument,
InviteCodeDocument,
MilestoneDocument,
NotificationDocument,
@@ -100,7 +100,7 @@ const db = {
milestones: monkDB.get<MilestoneDocument>("milestones"),
"user-milestones": monkDB.get<UserMilestoneDocument>("user-milestones"),
users: monkDB.get<PrivateUserDocument>("users"),
imports: monkDB.get<ImportDocument>("imports"),
imports: monkDB.get<KTBlackImportDocument>("imports"),
notifications: monkDB.get<NotificationDocument>("notifications"),
sessions: monkDB.get<SessionDocument>("sessions"),
"iidx-bpi-data": monkDB.get<IIDXBPIData>("iidx-bpi-data"),
@@ -8,13 +8,13 @@ import {
integer,
} from "kamaitachi-common";
import { ImportInputParser, KtLogger, ScorePlaytypeMap } from "../../types";
import { InsertQueue } from "./score-importing/insert-score";
import { ImportAllIterableData } from "./score-importing/score-importing";
import { CreateImportLoggerAndID } from "./common/import-logger";
import { CreateSessions } from "./sessions/sessions";
import { GetMilisecondsSince } from "../../core/hrtime-core";
import { ProcessPBs } from "./pb/process-pbs";
import { UpdateUsersGamePlaytypeStats } from "./user-game-stats/update-ugs";
import db from "../../db/db";
export default async function ScoreImportMain<D, C>(
user: PublicUserDocument,
@@ -23,9 +23,14 @@ export default async function ScoreImportMain<D, C>(
InputParser: ImportInputParser<D, C>
) {
const timeStarted = Date.now();
// We create an "import logger" - this holds a reference to the user's name for any future debugging.
const { importID, logger } = CreateImportLoggerAndID(user, importType);
logger.verbose("Received import request.");
// --- 1. Parsing ---
// We get an iterable from the provided parser function, alongside some context and a converter function.
// This iterable does not have to be an array - it's anything that's iterable, like a generator or similar.
const parseTimeStart = process.hrtime.bigint();
const { iterable, ConverterFunction, context, idStrings, game } = await InputParser(logger);
@@ -33,8 +38,9 @@ export default async function ScoreImportMain<D, C>(
logger.verbose(`Parsing took ${parseTime} miliseconds.`);
// --- 2. Importing ---
// ImportAllIterableData iterates over the iterable, applying the converter function to each bit of data.
const importTimeStart = process.hrtime.bigint();
let importInfo = await ImportAllIterableData(
user.id,
iterable,
@@ -43,26 +49,21 @@ export default async function ScoreImportMain<D, C>(
logger
);
// Flush the score queue out after importing.
let emptied = await InsertQueue();
if (emptied) {
logger.verbose(`Emptied ${emptied} documents from score queue.`);
}
const importTime = GetMilisecondsSince(importTimeStart);
logger.verbose(
`Importing took ${importTime} miliseconds. (${importTime / importInfo.length}ms/doc)`
);
// --- 3. ParseImportInfo ---
// ImportInfo is a relatively complex structure. We need some information from it for subsequent steps
// such as the list of chartIDs involved in this import.
let { scorePlaytypeMap, errors, scoreIDs, chartIDs } = ParseImportInfo(importInfo);
// Update user's rating information
// @todo
// --- 4. Sessions ---
// We create (or update existing) sessions here. This uses the aforementioned parsed import info
// to determine what goes where.
const sessionTimeStart = process.hrtime.bigint();
let sessionInfo = await CreateSessions(user.id, importType, game, scorePlaytypeMap, logger);
const sessionTime = GetMilisecondsSince(sessionTimeStart);
@@ -73,18 +74,23 @@ export default async function ScoreImportMain<D, C>(
}ms/doc).`
);
// Update user's PBs and set flags
// --- 5. PersonalBests ---
// We want to keep an updated reference of a users best score on a given chart.
// This function also handles conjoining different scores together (such as unioning best lamp and
// best score).
await ProcessPBs(user.id, chartIDs, logger);
let playtypes = Object.keys(scorePlaytypeMap) as Playtypes[Game][];
// i have honestly no idea what to do with this information.
// --- 6. Game Stats ---
// This function updates the users "stats" for this game - such as their profile rating, or their classes.
let classDeltas = await UpdateUsersGameStats(game, playtypes, user.id, logger);
// Update user's goals
// --- 7. Goals ---
// @todo
// Create import document
// --- 8. Finalise Import Document ---
// Create and Save an import document to the database, and finish everything up!
const ImportDocument: KTBlackImportDocument = {
importType,
idStrings: idStrings,
@@ -99,21 +105,27 @@ export default async function ScoreImportMain<D, C>(
userIntent,
};
logger.info(
`Import took: ${ImportDocument.timeFinished - timeStarted}ms, with ${
importInfo.length
} documents (Fails: ${errors.length}, Successes: ${scoreIDs.length}, Sessions: ${
sessionInfo.length
}). Aprx ${(ImportDocument.timeFinished - timeStarted) / importInfo.length}ms/doc`
);
const logMessage = `Import took: ${ImportDocument.timeFinished - timeStarted}ms, with ${
importInfo.length
} documents (Fails: ${errors.length}, Successes: ${scoreIDs.length}, Sessions: ${
sessionInfo.length
}). Aprx ${(ImportDocument.timeFinished - timeStarted) / importInfo.length}ms/doc`;
// Add this to the imports database
// @todo
// I only really want to log "big" imports. The others are here for debugging purposes.
if (scoreIDs.length > 500) {
logger.info(logMessage);
} else if (scoreIDs.length > 1) {
logger.verbose(logMessage);
} else {
logger.debug(logMessage);
}
await db.imports.insert(ImportDocument);
return ImportDocument;
}
function UpdateUsersGameStats(
async function UpdateUsersGameStats(
game: Game,
playtypes: Playtypes[Game][],
userID: integer,
@@ -121,12 +133,12 @@ function UpdateUsersGameStats(
) {
let promises = [];
// Update user's classes
for (const pt of playtypes) {
promises.push(UpdateUsersGamePlaytypeStats(game, pt, userID, null, logger));
}
return Promise.all(promises).then((r) => r.flat(1));
const r = await Promise.all(promises);
return r.flat(1);
}
function ParseImportInfo(importInfo: ImportProcessingInfo[]) {
@@ -7,7 +7,7 @@ import {
} from "kamaitachi-common";
import { DryScore, ConverterFunction, ConverterFnReturn, KtLogger } from "../../../types";
import HydrateScore from "./hydrate-score";
import { QueueScoreInsert, ScoreIDs } from "./insert-score";
import { InsertQueue, QueueScoreInsert, ScoreIDs } from "./insert-score";
import {
ConverterFailure,
InternalFailure,
@@ -78,6 +78,14 @@ export async function ImportAllIterableData<D, C>(
logger.verbose(`Recieved ${flatDatapoints.length} returns, from ${promises.length} data.`);
// Flush the score queue out after finishing most of the import. This ensures no scores get left in the
// queue.
let emptied = await InsertQueue();
if (emptied) {
logger.verbose(`Emptied ${emptied} documents from score queue.`);
}
return flatDatapoints;
}