diff --git a/.vscode/settings.json b/.vscode/settings.json index 65a245e25..d8909a3a2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,7 @@ "files.eol": "\n", "editor.detectIndentation": true, "typescript.tsdk": "node_modules/typescript/lib", + "typescript.tsserver.maxTsServerMemory": 16384, "[json]": { "files.insertFinalNewline": true, "files.trimFinalNewlines": false diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index f5bcc5e5b..8bee322c7 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -256,20 +256,26 @@ export default class RecordModel { export function apply(ctx: Context) { // Mark problem as deleted - ctx.on('problem/delete', (domainId, docId) => RecordModel.coll.deleteMany({ domainId, pid: docId })); + ctx.on('problem/delete', (domainId, docId) => Promise.all([ + RecordModel.coll.deleteMany({ domainId, pid: docId }), + RecordModel.collStat.deleteMany({ domainId, pid: docId }), + ])); ctx.on('domain/delete', (domainId) => RecordModel.coll.deleteMany({ domainId })); - ctx.on('record/judge', (rdoc, updated) => { - if (rdoc.status === STATUS.STATUS_ACCEPTED && updated) { - RecordModel.collStat.insertOne({ + ctx.on('record/judge', async (rdoc, updated) => { + if (rdoc.status === STATUS.STATUS_ACCEPTED && updated && !rdoc.contest) { + await RecordModel.collStat.updateOne({ _id: rdoc._id, - domainId: rdoc.domainId, - pid: rdoc.pid, - uid: rdoc.uid, - time: rdoc.time, - memory: rdoc.memory, - length: rdoc.code?.length || 0, - lang: rdoc.lang, - }); + }, { + $set: { + domainId: rdoc.domainId, + pid: rdoc.pid, + uid: rdoc.uid, + time: rdoc.time, + memory: rdoc.memory, + length: rdoc.code?.length || 0, + lang: rdoc.lang, + }, + }, { upsert: true }); } }); ctx.on('ready', async () => { diff --git a/packages/hydrooj/src/model/schedule.ts b/packages/hydrooj/src/model/schedule.ts index 4c78f7ea6..c002a15ba 100644 --- a/packages/hydrooj/src/model/schedule.ts +++ b/packages/hydrooj/src/model/schedule.ts @@ -1,8 +1,11 @@ import moment from 'moment-timezone'; import { Filter, ObjectId } from 'mongodb'; +import { Time } from '@hydrooj/utils'; +import { STATUS } from '@hydrooj/utils/lib/status'; import { Context } from '../context'; import { Schedule } from '../interface'; import { Logger } from '../logger'; +import { ContestModel, DocumentModel } from '../plugin-api'; import db from '../service/db'; import type { WorkerService } from '../service/worker'; import RecordModel from './record'; @@ -64,6 +67,29 @@ export async function apply(ctx: Context) { ScheduleModel.Worker = c.worker; c.worker.addHandler('task.daily', async () => { await RecordModel.coll.deleteMany({ contest: { $in: [RecordModel.RECORD_PRETEST, RecordModel.RECORD_GENERATE] } }); + const tdocs = await db.collection('document').find({ + docType: DocumentModel.TYPE_CONTEST, + endAt: { $gt: new Date(Date.now() - 2 * Time.day) }, + }).project({ docId: 1, beginAt: 1 }).toArray(); + const first = Math.min(...tdocs.map((i) => i.beginAt.getTime())); + const bulk = RecordModel.collStat.initializeUnorderedBulkOp(); + const cursor = RecordModel.coll.find({ + status: STATUS.STATUS_ACCEPTED, + contest: { $in: tdocs.map((i) => i.docId) }, + _id: { $gt: Time.getObjectID(new Date(first)) }, + }); + for await (const rdoc of cursor) { + bulk.find({ _id: rdoc._id }).upsert().updateOne({ + domainId: rdoc.domainId, + pid: rdoc.pid, + uid: rdoc.uid, + time: rdoc.time, + memory: rdoc.memory, + length: rdoc.code?.length || 0, + lang: rdoc.lang, + }); + } + await bulk.execute(); await global.Hydro.script.rp?.run({}, new Logger('task/rp').debug); await global.Hydro.script.problemStat?.run({}, new Logger('task/problem').debug); if (global.Hydro.model.system.get('server.checkUpdate') && !(new Date().getDay() % 3)) { diff --git a/packages/hydrooj/src/upgrade.ts b/packages/hydrooj/src/upgrade.ts index 37b03b2a6..a1228e8d1 100644 --- a/packages/hydrooj/src/upgrade.ts +++ b/packages/hydrooj/src/upgrade.ts @@ -650,11 +650,13 @@ const scripts: UpgradeScript[] = [ }); }, async function _88_89() { - const cursor = RecordModel.getMulti(undefined, { status: STATUS.STATUS_ACCEPTED }); - let bulk = []; + const cursor = RecordModel.getMulti(undefined, { + status: STATUS.STATUS_ACCEPTED, + contest: { $nin: [RecordModel.RECORD_PRETEST, RecordModel.RECORD_GENERATE] }, + }); + let bulk = RecordModel.collStat.initializeUnorderedBulkOp(); for await (const doc of cursor) { - bulk.push({ - _id: doc._id, + bulk.find({ _id: doc._id }).upsert().updateOne({ domainId: doc.domainId, pid: doc.pid, uid: doc.uid, @@ -663,12 +665,12 @@ const scripts: UpgradeScript[] = [ length: doc.code?.length || 0, lang: doc.lang, }); - if (bulk.length > 500) { - await RecordModel.collStat.insertMany(bulk); - bulk = []; + if (bulk.batches.length > 500) { + await bulk.execute(); + bulk = RecordModel.collStat.initializeUnorderedBulkOp(); } } - if (bulk.length) await RecordModel.collStat.insertMany(bulk); + if (bulk.batches.length) await bulk.execute(); return true; }, ]; diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 7f6748d27..267715f75 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.50.0", + "version": "4.50.1", "author": "undefined ", "license": "AGPL-3.0", "main": "index.ts", diff --git a/packages/ui-default/templates/problem_statistics.html b/packages/ui-default/templates/problem_statistics.html index c95b7283b..d15ba3de1 100644 --- a/packages/ui-default/templates/problem_statistics.html +++ b/packages/ui-default/templates/problem_statistics.html @@ -77,7 +77,7 @@