评测列表实时更新&评测机接口更换为socket

pull/1/head
masnn 5 years ago
parent f055d79fef
commit ec727d58aa

@ -1,42 +1,21 @@
const
{ requirePerm } = require('./tools'),
{ sleep } = require('../utils'),
{ PERM_JUDGE } = require('../permission'),
record = require('../model/record'),
problem = require('../model/problem'),
bus = require('../service/bus'),
queue = require('../service/queue'),
{ GET, POST } = require('../service/server');
{ GET, POST, SOCKET } = require('../service/server');
queue.assert('judge');
GET('/judge/noop', requirePerm(PERM_JUDGE), async ctx => {
ctx.body = {};
});
GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => {
let rid = await queue.get('judge', false);
if (rid) {
let rdoc = await record.get(rid);
let pdoc = await problem.getById(rdoc.pid);
let task = {
event: 'judge',
rid, type: 0,
pid: rdoc.pid,
data: pdoc.data,
lang: rdoc.lang,
code: rdoc.code
};
ctx.body = { task };
}
else ctx.body = {};
});
POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => {
console.log(ctx.request.body);
let body = ctx.request.body;
async function next(body) {
let rdoc = await record.get(body.rid);
let $set = {};
if (body.case) {
rdoc.testCases.push(body.case);
$set.testCases = rdoc.testCases;
rdoc.cases.push(body.case);
$set.cases = rdoc.cases;
}
if (body.judge_text) {
rdoc.judgeTexts.push(body.judge_text);
@ -52,22 +31,20 @@ POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => {
if (body.memory_kb) $set.memory = body.memory_kb;
rdoc = await record.update(body.rid, $set);
bus.publish('record_change', rdoc);
ctx.body = {};
});
POST('/judge/end', requirePerm(PERM_JUDGE), async ctx => {
let body = ctx.request.body;
}
async function end(body) {
let rdoc = await record.get(body.rid);
let $set = {};
if (body.case) {
rdoc.testCases.push(body.case);
$set.testCases = rdoc.testCases;
rdoc.cases.push(body.case);
$set.cases = rdoc.cases;
}
if (body.judge_text) {
rdoc.judgeTexts.push(body.judge_text);
$set.judgeTexts = rdoc.judgeTexts;
}
if (body.compiler_text) {
rdoc.compilerTexts.push(body.compilerTexts);
rdoc.compilerTexts.push(body.compiler_text);
$set.compilerTexts = rdoc.compilerTexts;
}
if (body.status) $set.status = body.status;
@ -75,8 +52,71 @@ POST('/judge/end', requirePerm(PERM_JUDGE), async ctx => {
if (body.time_ms) $set.time = body.time_ms;
if (body.memory_kb) $set.memory = body.memory_kb;
$set.judgeAt = new Date();
$set.judger = ctx.state.user._id;
$set.judger = body.judger;
rdoc = await record.update(body.rid, $set);
bus.publish('record_change', rdoc);
}
GET('/judge/noop', requirePerm(PERM_JUDGE), async ctx => {
ctx.body = {};
});
GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => {
let rid = await queue.get('judge', false);
if (rid) {
let rdoc = await record.get(rid);
let pdoc = await problem.getById(rdoc.pid);
let task = {
event: 'judge',
rid, type: 0,
pid: rdoc.pid,
data: pdoc.data,
lang: rdoc.lang,
code: rdoc.code
};
ctx.body = { task };
}
else ctx.body = {};
});
SOCKET('/judge/conn', [requirePerm(PERM_JUDGE)], async conn => {
let isOpen = true, processing = null;
conn.on('close', async () => {
isOpen = false;
if (processing) {
await record.reset(processing);
queue.push('judge', processing);
}
});
conn.on('data', async message => {
message = JSON.parse(message);
if (message.key == 'next') await next(message);
else if (message.key == 'end') {
await end(Object.assign({ judger: conn.state.user._id }, message));
processing = null;
}
});
while (isOpen) {
if (!processing) {
let rid = await queue.get('judge');
let rdoc = await record.get(rid);
let pdoc = await problem.getById(rdoc.pid);
let task = {
event: 'judge',
rid, type: 0,
pid: rdoc.pid,
data: pdoc.data,
lang: rdoc.lang,
code: rdoc.code
};
conn.write(JSON.stringify({ task }));
processing = task.rid;
} else await sleep(100);
}
});
POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => {
await next(ctx.request.body);
ctx.body = {};
});
POST('/judge/end', requirePerm(PERM_JUDGE), async ctx => {
await end(Object.assign({ judger: ctx.state.user._id }, ctx.request.body));
ctx.body = {};
});

@ -15,7 +15,7 @@ GET('/r', async ctx => {
ctx.templateName = 'record_main.html';
let q = {},
page = ctx.query.page || 1;
let rdocs = await record.getMany(q, { rid: 1 }, page, constants.RECORD_PER_PAGE);
let rdocs = await record.getMany(q, { _id: -1 }, page, constants.RECORD_PER_PAGE);
let pdict = {}, udict = {};
for (let rdoc of rdocs) {
udict[rdoc.uid] = await user.getById(rdoc.uid);
@ -39,6 +39,14 @@ SOCKET('/record-conn', [], conn => {
conn.send({ html: await conn.renderHTML('record_main_tr.html', { rdoc, udoc, pdoc }) });
}
bus.subscribe(['record_change'], onRecordChange);
conn.on('data', async message => {
console.log(message);
let { rids } = JSON.parse(message);
for (let rid of rids) {
let rdoc = await record.get(rid);
await onRecordChange({ value: rdoc });
}
});
conn.on('close', () => {
bus.unsubscribe(['record_change'], onRecordChange);
});

@ -25,7 +25,7 @@ module.exports = {
* @param {string} text
* @param {string} html
*/
async send_mail(to, subject, text, html) {
async sendMail(to, subject, text, html) {
let t;
try {
t = await new Promise((resolve, reject) => {

@ -43,7 +43,7 @@
<td class="col--status">
<span class="icon record-status--icon {{ builtin.STATUS_CODES[rcdoc['status']] }}"></span>
<span class="record-status--text {{ builtin.STATUS_CODES[rcdoc['status']] }}">
{{ status.STATUS_TEXTS[rcdoc['status']] }}
{{ builtin.STATUS_TEXTS[rcdoc['status']] }}
</span>
<span>{{ rcdoc['judgeText'] }}</span>
<a class="tool-button" href="/wiki/help#status"><span class="icon icon-help"></span></a>

@ -4,6 +4,9 @@
<script>
var Context = {
'socketUrl': "/record-conn",
'rids': [
{% for rdoc in rdocs %}"{{ rdoc._id.toString() }}",{% endfor %}
]
};
</script>
<div class="row">

@ -26,5 +26,5 @@
<td class="col--time">{% if rdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rdoc.time }}ms</td>
<td class="col--memory">{% if rdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rdoc.memory|format_size(1024) }}</td>
<td class="col--lang">{{ builtin.LANG_TEXTS[rdoc['lang']] }}</td>
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generationTime)|safe }}</td>
<td class="col--submit-at">{{ datetime_span(rdoc['_id'])|safe }}</td>
</tr>

@ -8,6 +8,12 @@ const page = new NamedPage('record_main', async () => {
const sock = new SockJs(Context.socketUrl);
const dd = new DiffDOM();
sock.onopen = () => {
sock.send(document.cookie);
setTimeout(() => {
sock.send(JSON.stringify({ rdocs: Context.rids }));
}, 300);
};
sock.onmessage = (message) => {
const msg = JSON.parse(message.data);
const $newTr = $(msg.html);

Loading…
Cancel
Save