refactor(remote_judger): waitForSubmission

This commit is contained in:
Baoshuo Ren 2023-02-06 11:24:45 +08:00
parent 00fea4675f
commit 4c0167ee6e
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
7 changed files with 447 additions and 417 deletions

View File

@ -20,10 +20,10 @@ export interface IBasicProvider {
end: NextFunction end: NextFunction
): Promise<string | void>; ): Promise<string | void>;
waitForSubmission( waitForSubmission(
problem_id: string,
id: string, id: string,
next: NextFunction, next: NextFunction,
end: NextFunction end: NextFunction,
problem_id?: string
): Promise<void>; ): Promise<void>;
} }

View File

@ -8,7 +8,7 @@ import Logger from '../utils/logger';
proxy(superagent); proxy(superagent);
const logger = new Logger('remote/atcoder'); const logger = new Logger('remote/atcoder');
const langs_map = { const LANGS_MAP = {
C: { C: {
name: 'C (GCC 9.2.1)', name: 'C (GCC 9.2.1)',
id: 4001, id: 4001,
@ -182,7 +182,7 @@ export default class AtcoderProvider implements IBasicProvider {
next, next,
end end
) { ) {
const programType = langs_map[lang] || langs_map['C++']; const programType = LANGS_MAP[lang] || LANGS_MAP['C++'];
const comment = programType.comment; const comment = programType.comment;
if (comment) { if (comment) {
@ -244,31 +244,24 @@ export default class AtcoderProvider implements IBasicProvider {
.getAttribute('data-id'); .getAttribute('data-id');
} }
async waitForSubmission(problem_id: string, id: string, next, end) { async waitForSubmission(id: string, next, end, problem_id: string) {
let i = 0; let count = 0;
let fail = 0;
const [contestId] = parseProblemId(problem_id); const [contestId] = parseProblemId(problem_id);
const status_url = `/contests/${contestId}/submissions/me/status/json?reload=true&sids[]=${id}`; const status_url = `/contests/${contestId}/submissions/me/status/json?reload=true&sids[]=${id}`;
while (true) { while (count < 180 && fail < 10) {
if (++i > 180) { count++;
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
await sleep(1000); await sleep(1000);
const { body, error, header } = await this.get(status_url).retry(3);
try {
const { body, header } = await this.get(status_url).retry(3);
if (header['set-cookie']) { if (header['set-cookie']) {
this.cookie = header['set-cookie']; this.cookie = header['set-cookie'];
} }
if (error) continue;
const result = body.Result[id]; const result = body.Result[id];
const { const {
window: { document }, window: { document },
@ -290,7 +283,8 @@ export default class AtcoderProvider implements IBasicProvider {
if ( if (
statusElem.title === 'Judging' || statusElem.title === 'Judging' ||
(statusTd.colSpan == 3 && statusTd.className.includes('waiting-judge')) (statusTd.colSpan == 3 &&
statusTd.className.includes('waiting-judge'))
) { ) {
await next({ test_id: /(\d+)/.exec(statusElem.innerHTML)[1] || 0 }); await next({ test_id: /(\d+)/.exec(statusElem.innerHTML)[1] || 0 });
@ -328,6 +322,18 @@ export default class AtcoderProvider implements IBasicProvider {
time, time,
memory, memory,
}); });
} catch (e) {
logger.error(e);
fail++;
} }
} }
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
} }

View File

@ -344,27 +344,22 @@ export default class CodeforcesProvider implements IBasicProvider {
.getAttribute('data-submission-id'); .getAttribute('data-submission-id');
} }
async waitForSubmission(problem_id: string, id: string, next, end) { async waitForSubmission(id: string, next, end) {
let i = 0; let count = 0;
let fail = 0;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
while (count < 180 && fail < 10) {
count++;
await sleep(1000); await sleep(1000);
const { body, error } = await this.post('/data/submitSource')
try {
const { body } = await this.post('/data/submitSource')
.send({ .send({
csrf_token: this.csrf, csrf_token: this.csrf,
submissionId: id, submissionId: id,
}) })
.retry(3); .retry(3);
if (error) continue;
if (body.compilationError === 'true') { if (body.compilationError === 'true') {
return await end({ return await end({
id, id,
@ -373,6 +368,7 @@ export default class CodeforcesProvider implements IBasicProvider {
message: crlf(body['checkerStdoutAndStderr#1'], LF), message: crlf(body['checkerStdoutAndStderr#1'], LF),
}); });
} }
const time = mathSum( const time = mathSum(
Object.keys(body) Object.keys(body)
.filter(k => k.startsWith('timeConsumed#')) .filter(k => k.startsWith('timeConsumed#'))
@ -385,6 +381,7 @@ export default class CodeforcesProvider implements IBasicProvider {
.map(k => +body[k]) .map(k => +body[k])
) / 1024; ) / 1024;
await next({ test_id: body.testCount }); await next({ test_id: body.testCount });
if (body.waiting === 'true') continue; if (body.waiting === 'true') continue;
const testCount = +body.testCount; const testCount = +body.testCount;
@ -442,6 +439,18 @@ export default class CodeforcesProvider implements IBasicProvider {
memory, memory,
details, details,
}); });
} catch (e) {
logger.error(e);
fail++;
} }
} }
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
} }

View File

@ -285,7 +285,7 @@ export default class LibreojProvider implements IBasicProvider {
return user_id === submission_user_id; return user_id === submission_user_id;
} }
async waitForSubmission(problem_id: string, id: string, next, end) { async waitForSubmission(id: string, next, end, problem_id: string) {
if (!(await this.ensureLogin())) { if (!(await this.ensureLogin())) {
await end({ await end({
error: true, error: true,
@ -296,25 +296,18 @@ export default class LibreojProvider implements IBasicProvider {
return null; return null;
} }
let i = 0; let count = 0;
let fail = 0;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
while (count < 180 && fail < 10) {
count++;
await sleep(1000); await sleep(1000);
const { body, error } = await this.post('/submission/getSubmissionDetail')
try {
const { body } = await this.post('/submission/getSubmissionDetail')
.send({ submissionId: String(id), locale: 'zh_CN' }) .send({ submissionId: String(id), locale: 'zh_CN' })
.retry(3); .retry(3);
if (error) continue;
if (body.meta.problem.displayId != problem_id) { if (body.meta.problem.displayId != problem_id) {
return await end({ return await end({
id, id,
@ -377,7 +370,8 @@ export default class LibreojProvider implements IBasicProvider {
body.progress.testcaseResult[testcase.testcaseHash].status !== body.progress.testcaseResult[testcase.testcaseHash].status !==
'Accepted' 'Accepted'
) { ) {
result = body.progress.testcaseResult[testcase.testcaseHash].status; result =
body.progress.testcaseResult[testcase.testcaseHash].status;
break; break;
} }
@ -407,9 +401,9 @@ export default class LibreojProvider implements IBasicProvider {
test_info += `<test num="${ test_info += `<test num="${
index + 1 index + 1
}" info="${status}" time="${Math.round(testcase.time || 0)}" memory="${ }" info="${status}" time="${Math.round(
testcase.memory testcase.time || 0
}">`; )}" memory="${testcase.memory}">`;
if (testcase.input) { if (testcase.input) {
if (typeof testcase.input === 'string') { if (typeof testcase.input === 'string') {
@ -495,7 +489,9 @@ export default class LibreojProvider implements IBasicProvider {
details += `<tests>${body.progress.subtasks details += `<tests>${body.progress.subtasks
.map( .map(
(subtask, index) => (subtask, index) =>
`<subtask num="${index + 1}" info="${getSubtaskStatusDisplayText( `<subtask num="${
index + 1
}" info="${getSubtaskStatusDisplayText(
subtask.testcases subtask.testcases
)}">${subtask.testcases )}">${subtask.testcases
.map((item, index) => .map((item, index) =>
@ -516,6 +512,18 @@ export default class LibreojProvider implements IBasicProvider {
memory: body.meta.memoryUsed, memory: body.meta.memoryUsed,
details: `<div>${details}</div>`, details: `<div>${details}</div>`,
}); });
} catch (e) {
logger.error(e);
fail++;
} }
} }
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
} }

View File

@ -250,11 +250,11 @@ export default class LuoguProvider implements IBasicProvider {
return result.body.rid; return result.body.rid;
} }
async waitForSubmission(problem_id: string, id: string, next, end) { async waitForSubmission(id: string, next, end) {
let fail = 0; let fail = 0;
let count = 0; let count = 0;
while (count < 180 && fail < 5) { while (count < 180 && fail < 10) {
await sleep(1000); await sleep(1000);
count++; count++;

View File

@ -9,7 +9,7 @@ import sleep from '../utils/sleep';
proxy(superagent); proxy(superagent);
const logger = new Logger('remote/uoj'); const logger = new Logger('remote/uoj');
const langs_map = { const LANGS_MAP = {
C: { C: {
name: 'C', name: 'C',
id: 'C', id: 'C',
@ -175,7 +175,7 @@ export default class UOJProvider implements IBasicProvider {
next, next,
end end
) { ) {
const programType = langs_map[lang] || langs_map['C++']; const programType = LANGS_MAP[lang] || LANGS_MAP['C++'];
const comment = programType.comment; const comment = programType.comment;
if (comment) { if (comment) {
@ -206,20 +206,15 @@ export default class UOJProvider implements IBasicProvider {
.innerHTML.split('#')[1]; .innerHTML.split('#')[1];
} }
async waitForSubmission(problem_id: string, id: string, next, end) { async waitForSubmission(id: string, next, end) {
let i = 0; let count = 0;
let fail = 0;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
while (count < 180 && fail < 10) {
count++;
await sleep(1000); await sleep(1000);
try {
const { text } = await this.get(`/submission/${id}`); const { text } = await this.get(`/submission/${id}`);
const { const {
window: { document }, window: { document },
@ -265,6 +260,18 @@ export default class UOJProvider implements IBasicProvider {
time, time,
memory, memory,
}); });
} catch (e) {
logger.error(e);
fail++;
} }
} }
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
} }

View File

@ -35,7 +35,7 @@ class AccountService {
if (!rid) return; if (!rid) return;
await this.api.waitForSubmission(problem_id, rid, next, end); await this.api.waitForSubmission(rid, next, end, problem_id);
} catch (e) { } catch (e) {
logger.error(e); logger.error(e);
@ -178,7 +178,7 @@ class VJudge {
if (!rid) return; if (!rid) return;
await provider.waitForSubmission(problem_id, rid, next, end); await provider.waitForSubmission(rid, next, end, problem_id);
} catch (e) { } catch (e) {
logger.error(e); logger.error(e);
@ -204,10 +204,10 @@ class VJudge {
if (await provider.ensureIsOwnSubmission(config.remote_submission_id)) { if (await provider.ensureIsOwnSubmission(config.remote_submission_id)) {
await provider.waitForSubmission( await provider.waitForSubmission(
problem_id,
config.remote_submission_id, config.remote_submission_id,
next, next,
end end,
problem_id
); );
} else { } else {
return await end({ return await end({