diff --git a/packages/hydrooj/src/handler/judge.ts b/packages/hydrooj/src/handler/judge.ts index c474f7427..e196b167b 100644 --- a/packages/hydrooj/src/handler/judge.ts +++ b/packages/hydrooj/src/handler/judge.ts @@ -78,7 +78,7 @@ export async function next(body: Partial) { $set, $push, $unset, $inc, } = processPayload(body); const rdoc = await record.update(body.domainId, body.rid, $set, $push, $unset, $inc); - bus.broadcast('record/change', rdoc, $set, $push, body); + if (rdoc) bus.broadcast('record/change', rdoc, $set, $push, body); return rdoc; } @@ -144,10 +144,9 @@ export async function end(body: Partial) { const $unset: any = { progress: '' }; $set.judgeAt = new Date(); $set.judger = body.judger ?? 1; - let rdoc = await record.update(body.domainId, body.rid, $set, $push, $unset); + const rdoc = await record.update(body.domainId, body.rid, $set, $push, $unset); + if (rdoc) bus.broadcast('record/change', rdoc, null, null, body); // trigger a full update await postJudge(rdoc); - rdoc = await record.get(body.rid); - bus.broadcast('record/change', rdoc, null, null, body); // trigger a full update return rdoc; } @@ -246,20 +245,17 @@ export class JudgeConnectionHandler extends ConnectionHandler { } async newTask(t: Task) { - const rdoc = await record.get(t.domainId, t.rid); - if (!rdoc) return; - - const rid = rdoc._id.toHexString(); + const rid = t.rid.toHexString(); let resolve: (_: any) => void; const p = new Promise((r) => { resolve = r; }); this.tasks[rid] = { queue: new PQueue({ concurrency: 1 }), - domainId: rdoc.domainId, + domainId: t.domainId, resolve, t, }; - this.send({ task: { ...rdoc, ...t } }); - this.tasks[rid].queue.add(() => next({ status: STATUS.STATUS_FETCHED, domainId: rdoc.domainId, rid: rdoc._id })); + this.send({ task: t }); + this.tasks[rid].queue.add(() => next({ status: STATUS.STATUS_FETCHED, domainId: t.domainId, rid: t.rid })); await p; delete this.tasks[rid]; } diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index 3b4174590..26b6715de 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -2,7 +2,7 @@ import { sum } from 'lodash'; import moment from 'moment-timezone'; import { - Filter, MatchKeysAndValues, + Filter, FindOptions, MatchKeysAndValues, ObjectId, OnlyFieldsOfType, PushOperator, UpdateFilter, } from 'mongodb'; import { Context } from '../context'; @@ -78,15 +78,23 @@ export default class RecordModel { }; } - static async judge(domainId: string, rids: MaybeArray, priority = 0, config: ProblemConfigFile = {}, meta: Partial = {}) { - rids = rids instanceof Array ? rids : [rids]; - if (!rids.length) return null; - const rdocs = await RecordModel.getMulti(domainId, { _id: { $in: rids } }).toArray(); + static async judge( + domainId: string, rids: MaybeArray | RecordDoc, priority = 0, + config: ProblemConfigFile = {}, meta: Partial = {}, + ) { + let rdocs: RecordDoc[]; + const _rids = rids instanceof Array ? rids + : (rids instanceof ObjectId) ? [rids] + : [rids._id]; + if (!_rids.length) return null; + if (rids instanceof Array || rids instanceof ObjectId || ObjectId.isValid(rids.toString())) { + rdocs = await RecordModel.getMulti(domainId, { _id: { $in: _rids } }, { readPreference: 'primary' }).toArray(); + } else rdocs = [rids]; if (!rdocs.length) return null; let source = `${domainId}/${rdocs[0].pid}`; let [pdoc] = await Promise.all([ problem.get(domainId, rdocs[0].pid), - task.deleteMany({ rid: { $in: rids } }), + task.deleteMany({ rid: { $in: _rids } }), ]); if (!pdoc) throw new ProblemNotFoundError(domainId, rdocs[0].pid); if (pdoc.reference) { @@ -102,8 +110,8 @@ export default class RecordModel { if (pdoc.config.type === 'remote_judge' && rdoc.contest?.toHexString() !== '0'.repeat(24)) type = 'remotejudge'; else if (meta?.type === 'generate') type = 'generate'; return ({ + ...rdoc, ...(pdoc.config as any), // TODO deprecate this - lang: rdoc.lang, priority, type, rid: rdoc._id, @@ -167,7 +175,7 @@ export default class RecordModel { bus.broadcast('record/change', data); if (addTask) { const priority = await RecordModel.submissionPriority(uid, args.type === 'pretest' ? -20 : (isContest ? 50 : 0)); - await RecordModel.judge(domainId, res.insertedId, priority, isContest ? { detail: false } : {}, { + await RecordModel.judge(domainId, data, priority, isContest ? { detail: false } : {}, { type: args.type, rejudge: data.rejudged, }); @@ -175,9 +183,9 @@ export default class RecordModel { return res.insertedId; } - static getMulti(domainId: string, query: any) { + static getMulti(domainId: string, query: any, options?: FindOptions) { if (domainId) query = { domainId, ...query }; - return RecordModel.coll.find(query); + return RecordModel.coll.find(query, options); } static getMultiStat(domainId: string, query: any, sortBy: any = { _id: -1 }) { @@ -208,7 +216,7 @@ export default class RecordModel { ); return res.value || null; } - return await RecordModel.get(domainId, _id); + return await RecordModel.coll.findOne({ _id }, { readPreference: 'primary' }); } static async updateMulti( diff --git a/packages/vjudge/src/index.ts b/packages/vjudge/src/index.ts index 19e9f0e6d..3417fc5a0 100644 --- a/packages/vjudge/src/index.ts +++ b/packages/vjudge/src/index.ts @@ -42,8 +42,6 @@ class AccountService { } async judge(task) { - const rdoc = await RecordModel.get(task.domainId, task.rid); - task = Object.assign(rdoc, task); const next = (payload) => JudgeHandler.next({ ...payload, rid: task.rid, domainId: task.domainId }); const end = (payload) => JudgeHandler.end({ ...payload, rid: task.rid, domainId: task.domainId }); await next({ status: STATUS.STATUS_FETCHED });