mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
judge: add tracing detail for judge case and fetch file
This commit is contained in:
6 files changed
+20
-10
No files matched your search
@@ -10,7 +10,7 @@ const defaultEnv = `\
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
HOME=/w
|
||||
# modify to your python version installed
|
||||
PYTHONPATH=/lib/python3.12/site-packages
|
||||
PYTHONPATH=/lib/python3.13/site-packages
|
||||
`;
|
||||
|
||||
export const JudgeSettings = Schema.object({
|
||||
@@ -28,7 +28,7 @@ export const JudgeSettings = Schema.object({
|
||||
singleTaskParallelism: Schema.number().default(2).min(1).step(1),
|
||||
rerun: Schema.number().description('Re-Run testcase if time-limit-exceeded (max per submission)').default(0).min(0).step(1),
|
||||
rate: Schema.number().default(1),
|
||||
env: Schema.string().default(defaultEnv),
|
||||
env: Schema.string().default(defaultEnv).role('textarea'),
|
||||
host: Schema.any(),
|
||||
secret: Schema.string().description('Judge Token Secret').default(randomstring(32)),
|
||||
disable: Schema.boolean().description('Disable builtin judge').default(false),
|
||||
|
||||
@@ -45,7 +45,12 @@ function judgeSubtask(subtask: NormalizedSubtask, sid: string, judgeCase: Task['
|
||||
time: 0,
|
||||
memory: 0,
|
||||
message: '',
|
||||
} : await runner(ctx, ctxSubtask, runner);
|
||||
} : await (async () => {
|
||||
using span = ctx.startChildSpan('judge.case', { id: subtask.cases[cid].id, subtaskId: subtask.id });
|
||||
const r = await runner(ctx, ctxSubtask, runner);
|
||||
span.setAttributes({ status: r?.status, time: r?.time, memory: r?.memory });
|
||||
return r;
|
||||
})();
|
||||
if (res?.status !== STATUS.STATUS_CANCELED) {
|
||||
ctxSubtask.score = Score[ctxSubtask.subtask.type](ctxSubtask.score, res.score);
|
||||
ctxSubtask.status = Math.max(ctxSubtask.status, res.status);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from 'path';
|
||||
import { SpanStatusCode } from '@opentelemetry/api';
|
||||
import PQueue from 'p-queue';
|
||||
import superagent from 'superagent';
|
||||
import WebSocket from 'ws';
|
||||
@@ -49,7 +50,7 @@ export default class Hydro implements Session {
|
||||
setInterval(() => { this.get(''); }, 30000000); // Cookie refresh only
|
||||
}
|
||||
|
||||
async fetchFile<T extends string | null>(namespace: T, files: Record<string, string>): Promise<T extends null ? string : null> {
|
||||
async fetchFile<T extends string | null>(namespace: T, files: Record<string, string>, ctx: JudgeTask): Promise<T extends null ? string : null> {
|
||||
if (!namespace) { // record-related resource (code)
|
||||
const name = Object.keys(files)[0].split('#')[0];
|
||||
const res = await this.post('judge/files', { id: name });
|
||||
@@ -71,9 +72,11 @@ export default class Hydro implements Session {
|
||||
});
|
||||
for (const name in res.body.links) {
|
||||
queue.add(async () => {
|
||||
using span = ctx.startChildSpan('judge.fetchFile', { name });
|
||||
if (name.includes('/')) await fs.ensureDir(path.dirname(files[name]));
|
||||
const w = fs.createWriteStream(files[name]);
|
||||
await pipeRequest(this.get(res.body.links[name]), w, 60000, name);
|
||||
span.setStatus({ code: SpanStatusCode.OK });
|
||||
});
|
||||
}
|
||||
await queue.onIdle();
|
||||
|
||||
@@ -27,7 +27,7 @@ export { JudgeRequest } from '@hydrooj/common';
|
||||
export interface Session {
|
||||
getLang: (name: string, doThrow?: boolean) => LangConfig;
|
||||
getReporter: (task: JudgeTask) => { next: NextFunction, end: NextFunction };
|
||||
fetchFile: <T extends null | string>(namespace: T, files: Record<string, string>) => Promise<T extends null ? string : null>;
|
||||
fetchFile: <T extends null | string>(namespace: T, files: Record<string, string>, ctx: JudgeTask) => Promise<T extends null ? string : null>;
|
||||
postFile: (target: string, filename: string, file: string) => Promise<void>;
|
||||
config: { detail: DetailType, host?: string, trusted?: boolean };
|
||||
}
|
||||
@@ -12,7 +12,7 @@ export async function judge(ctx: Context) {
|
||||
ctx.compileLocalFile('checker', ctx.config.checker, ctx.config.checker_type),
|
||||
ctx.compileLocalFile('validator', ctx.config.validator),
|
||||
(async () => {
|
||||
const f = await ctx.session.fetchFile(null, { [ctx.files.hack]: '' });
|
||||
const f = await ctx.session.fetchFile(null, { [ctx.files.hack]: '' }, ctx);
|
||||
ctx.pushClean(() => fs.unlink(f));
|
||||
return f;
|
||||
})(),
|
||||
|
||||
@@ -51,7 +51,7 @@ export class JudgeTask {
|
||||
logger.debug('%o', request);
|
||||
}
|
||||
|
||||
private startChildSpan(name: string, attributes?: Record<string, any>) {
|
||||
startChildSpan(name: string, attributes?: Record<string, any>) {
|
||||
const span = this.tracer.startSpan(name, { attributes }, this.mainContext);
|
||||
span[Symbol.dispose] = () => span.end();
|
||||
return span as typeof span & { [Symbol.dispose]: () => void };
|
||||
@@ -142,13 +142,14 @@ export class JudgeTask {
|
||||
const allFilesToRemove = Object.keys(etags).filter((name) => !allFiles.has(name) && fs.existsSync(join(filePath, name)));
|
||||
await Promise.all(allFilesToRemove.map((name) => fs.remove(join(filePath, name))));
|
||||
if (filenames.length) {
|
||||
span.setAttribute('syncedFiles', filenames.length);
|
||||
span.setAttribute('files', filenames);
|
||||
logger.info(`Getting problem data: ${this.session?.config.host || 'local'}/${source}`);
|
||||
this.next({ message: 'Syncing testdata, please wait...' });
|
||||
this.mainContext = trace.setSpan(context.active(), span);
|
||||
await this.session.fetchFile(source, Object.fromEntries(
|
||||
files.filter((i) => filenames.includes(i.name))
|
||||
.map((i) => [i.name, join(filePath, i.name)]),
|
||||
));
|
||||
), this);
|
||||
this.compileCache = {};
|
||||
}
|
||||
if (allFilesToRemove.length || filenames.length) {
|
||||
@@ -161,6 +162,7 @@ export class JudgeTask {
|
||||
logger.warn('CacheOpen Fail: %s %o %o', source, files, e);
|
||||
throw e;
|
||||
} finally {
|
||||
this.mainContext = trace.setSpan(context.active(), this.span);
|
||||
Lock.release(filePath);
|
||||
}
|
||||
}
|
||||
@@ -168,7 +170,7 @@ export class JudgeTask {
|
||||
async doSubmission() {
|
||||
this.folder = await this.cacheOpen(this.source, this.data);
|
||||
if (this.files?.code) {
|
||||
const target = await this.session.fetchFile(null, { [this.files.code]: '' });
|
||||
const target = await this.session.fetchFile(null, { [this.files.code]: '' }, this);
|
||||
this.code = { src: target };
|
||||
this.clean.push(() => fs.remove(target));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user