core: add controlled rejudge (#969)

Co-authored-by: panda <panda_dtdyy@outlook.com>
This commit is contained in:
undefinedandpanda authored and GitHub committed 2025-04-01 11:34:06 +01:00
1 parent 536c697f4b
commit 466bc984bd
12 files changed
+170 -119

No files matched your search

+7 -16
View File
@@ -4,8 +4,8 @@ import path from 'path';
import { fs } from '@hydrooj/utils';
import * as sysinfo from '@hydrooj/utils/lib/sysinfo';
import {
Context as HydroContext, db, JudgeHandler, JudgeResultBody, ObjectId, RecordModel,
SettingModel, StorageModel, SystemModel, TaskModel,
Context as HydroContext, db, JudgeHandler, JudgeResultCallbackContext,
ObjectId, RecordModel, SettingModel, StorageModel, SystemModel, TaskModel,
} from 'hydrooj';
import { langs } from 'hydrooj/src/model/setting';
import { getConfig } from '../config';
@@ -32,20 +32,11 @@ const session: Session = {
}
return null;
},
getNext(t: Context) {
t._callbackAwait ||= Promise.resolve();
return (data: Partial<JudgeResultBody>) => {
logger.debug('Next: %o', data);
if (data.case) data.case.message ||= '';
t._callbackAwait = t._callbackAwait.then(() => JudgeHandler.next({ ...data, rid: t.rid, domainId: t.request.domainId }));
};
},
getEnd(t: Context) {
t._callbackAwait ||= Promise.resolve();
return (data: Partial<JudgeResultBody>) => {
data.key = 'end';
logger.info('End: status=%d score=%d time=%dms memory=%dkb', data.status, data.score, data.time, data.memory);
t._callbackAwait = t._callbackAwait.then(() => JudgeHandler.end({ ...data, rid: t.rid, domainId: t.request.domainId }));
getReporter(t: Context) {
const reporter = new JudgeResultCallbackContext(app, t.request);
return {
next: (a) => reporter.next(a),
end: (a) => reporter.end(a),
};
},
getLang(lang: string, doThrow = true) {
+4 -6
View File
@@ -106,8 +106,8 @@ export default class Hydro implements Session {
this.ws.send(JSON.stringify({ ...data, rid, key }));
}
getNext(t: JudgeTask) {
return (data: Partial<JudgeResultBody>) => {
getReporter(t: JudgeTask) {
const next = (data: Partial<JudgeResultBody>) => {
log.debug('Next: %o', data);
const performanceMode = getConfig('performance') || t.meta.rejudge || t.meta.hackRejudge;
if (performanceMode && data.case && !data.compilerText && !data.message) {
@@ -119,14 +119,12 @@ export default class Hydro implements Session {
this.send(t.request.rid, 'next', data);
}
};
}
getEnd(t: JudgeTask) {
return (data: Partial<JudgeResultBody>) => {
const end = (data: Partial<JudgeResultBody>) => {
log.info('End: %o', data);
if (t.callbackCache) data.cases = t.callbackCache;
this.send(t.request.rid, 'end', data);
};
return { next, end };
}
async consume(queue: PQueue) {
+4 -6
View File
@@ -79,18 +79,16 @@ export default class VJ4 implements Session {
this.ws.send(JSON.stringify({ ...data, tag, key }));
}
getNext(t: JudgeTask) {
return (data: Partial<JudgeResultBody>) => {
getReporter(t: JudgeTask) {
const next = (data: Partial<JudgeResultBody>) => {
log.debug('Next: %o', data);
this.send((t.request as any).tag, 'next', data);
};
}
getEnd(t: JudgeTask) {
return (data: Partial<JudgeResultBody>) => {
const end = (data: Partial<JudgeResultBody>) => {
log.info('End: %o', data);
this.send((t.request as any).tag, 'end', data);
};
return { next, end };
}
get(url: string) {
+1 -2
View File
@@ -24,8 +24,7 @@ export { JudgeRequest } from '@hydrooj/common';
export interface Session {
getLang: (name: string, doThrow?: boolean) => LangConfig;
getNext: (task: JudgeTask) => NextFunction;
getEnd: (task: JudgeTask) => NextFunction;
getReporter: (task: JudgeTask) => { next: NextFunction, end: NextFunction };
fetchFile: <T extends null | string>(namespace: T, files: Record<string, string>) => Promise<T extends null ? string : null>;
postFile: (target: string, filename: string, file: string) => Promise<void>;
config: { detail: boolean, host?: string, trusted?: boolean };
@@ -22,8 +22,6 @@ export interface RuntimeContext {
executeInteractor?: Execute;
executeManager?: Execute;
executeUser?: Execute;
_callbackAwait?: Promise<any>;
}
export interface ContextSubTask {
+1 -2
View File
@@ -70,8 +70,7 @@ export class JudgeTask {
HYDRO_USER: (this.request.uid || 0).toString(),
HYDRO_CONTEST: tid,
};
this.next = this.session.getNext(this);
this.end = this.session.getEnd(this);
Object.assign(this, this.session.getReporter(this));
logger.info('Submission: %s/%s/%s', host, this.source, this.rid);
await this.doSubmission();
} catch (e) {