From a8d7d86e01faa14fd612acc18f818718df3bff0c Mon Sep 17 00:00:00 2001 From: hewenyang Date: Tue, 13 Feb 2018 15:46:01 +0800 Subject: [PATCH 1/7] Push run task to rabbitmq at web side --- config-example.json | 3 +- libs/judger.js | 41 +- package-lock.json | 1316 ++++++++++++------------------------------- package.json | 3 + 4 files changed, 405 insertions(+), 958 deletions(-) diff --git a/config-example.json b/config-example.json index 06d1a2a..c34c4f0 100644 --- a/config-example.json +++ b/config-example.json @@ -167,6 +167,7 @@ ], "session_secret": "233", "judge_server_addr": "http://127.0.0.1:5284", + "rabbitMQ": "amqp://localhost/", "judge_token": "233", "email_jwt_secret": "test" -} \ No newline at end of file +} diff --git a/libs/judger.js b/libs/judger.js index 638bbff..85b40e5 100644 --- a/libs/judger.js +++ b/libs/judger.js @@ -2,7 +2,33 @@ const enums = require('./enums'), rp = require('request-promise'), url = require('url'); +const amqp = require('amqplib'); const util = require('util'); +const winston = require('winston'); +const msgPack = require('msgpack-lite'); + +let amqpConnection; +let publicChannel; + +async function connect () { + amqpConnection = await amqp.connect(syzoj.config.rabbitMQ); + publicChannel = await amqpConnection.createChannel(); + await publicChannel.assertQueue('judge', { + maxPriority: 5, + durable: true + }); + await publicChannel.assertQueue('result', { + durable: true + }); + await publicChannel.assertExchange('progress', 'fanout', { + durable: false + }); + amqpConnection.on('error', (err) => { + winston.error('RabbitMQ connection failure: ${err.toString()}'); + amqpConnection.close(); + process.exit(1); + }); +} module.exports.judge = async function (judge_state, problem, priority) { let type, param, extraFile = null; switch (problem.type) { @@ -44,13 +70,8 @@ module.exports.judge = async function (judge_state, problem, priority) { extraFileLocation: extraFile }; - await rp(url.resolve(syzoj.config.judge_server_addr, "/daemon/task"), { - method: 'PUT', - body: req, - headers: { - Token: syzoj.config.judge_token - }, - json: true, - simple: true - }); -} \ No newline at end of file + // TODO: parse extraFileLocation + publicChannel.sendToQueue('judge', msgPack.encode({ content: req.content, extraData: null }), { priority: priority }); +} + +connect(); diff --git a/package-lock.json b/package-lock.json index 71f98a6..41b2295 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,11 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=" }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "accepts": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", @@ -61,6 +66,41 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "optional": true }, + "amqplib": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "requires": { + "bitsyntax": "0.0.4", + "bluebird": "3.5.0", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.1.14", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -79,6 +119,20 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-0.1.0.tgz", "integrity": "sha1-bdxY+gg8e8VF08WZWygwzCNm1Eo=" }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", @@ -120,6 +174,11 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" }, + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + }, "async-lock": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-0.3.10.tgz", @@ -148,6 +207,11 @@ "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE=" }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, "base64-js": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", @@ -172,6 +236,14 @@ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.1.2.tgz", "integrity": "sha1-8725mtUmihX8HwvtL7AY4mk/4jY=" }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "requires": { + "buffer-more-ints": "0.0.2" + } + }, "bl": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", @@ -180,6 +252,14 @@ "readable-stream": "2.3.3" } }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, "bluebird": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", @@ -220,6 +300,15 @@ "hoek": "2.16.3" } }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, "buffer": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", @@ -240,6 +329,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=" + }, "buildmail": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-3.10.0.tgz", @@ -369,6 +463,11 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -395,6 +494,11 @@ "graceful-readlink": "1.0.1" } }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, "concat-stream": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", @@ -405,6 +509,11 @@ "typedarray": "0.0.6" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -556,6 +665,11 @@ } } }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -676,6 +790,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "depd": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", @@ -686,6 +805,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, "dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", @@ -889,6 +1013,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=" }, + "event-lite": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/event-lite/-/event-lite-0.1.1.tgz", + "integrity": "sha1-R88IqNN9C2lM23s7F7UfqsZXYIY=" + }, "express": { "version": "4.15.3", "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", @@ -950,6 +1079,11 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -1075,6 +1209,47 @@ } } }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, "generic-pool": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.2.tgz", @@ -1113,6 +1288,19 @@ } } }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, "got": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", @@ -1166,6 +1354,11 @@ "har-schema": "1.0.5" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, "hawk": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", @@ -1254,6 +1447,15 @@ "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -1264,6 +1466,11 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" }, + "int64-buffer": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.1.10.tgz", + "integrity": "sha1-J3siiofZWtd30HwTgyAiQGpHNCM=" + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -1367,7 +1574,14 @@ "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", "requires": { "argparse": "1.0.9", - "esprima": "2.7.3" + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + } } }, "jsbn": { @@ -1734,6 +1948,14 @@ "mime-db": "1.27.0" } }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -1789,6 +2011,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "msgpack-lite": { + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/msgpack-lite/-/msgpack-lite-0.1.26.tgz", + "integrity": "sha1-3TxQsm8FnyXn7e42REGDWOKprYk=", + "requires": { + "event-lite": "0.1.1", + "ieee754": "1.1.8", + "int64-buffer": "0.1.10", + "isarray": "1.0.0" + } + }, "multer": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/multer/-/multer-1.3.0.tgz", @@ -1863,6 +2096,24 @@ "win-spawn": "2.0.0" } }, + "node-pre-gyp": { + "version": "0.6.39", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", + "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", + "requires": { + "detect-libc": "1.0.3", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.1" + } + }, "nodemailer": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.1.0.tgz", @@ -1881,6 +2132,15 @@ "nodemailer-fetch": "1.6.0" } }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -1892,6 +2152,17 @@ "validate-npm-package-license": "3.0.1" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, "nth-check": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", @@ -1959,6 +2230,11 @@ "wordwrap": "1.0.0" } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", @@ -1972,6 +2248,15 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -2001,6 +2286,11 @@ "pinkie-promise": "2.0.1" } }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -2399,6 +2689,14 @@ "debug": "2.6.7" } }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, "rndm": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", @@ -2548,6 +2846,11 @@ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.1.0.tgz", "integrity": "sha1-l9c3cTf/u6tCVSLkKf4KqJpIizU=" }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, "slide": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", @@ -2610,944 +2913,7 @@ "integrity": "sha1-TLz5Zdi5AdGxAVy8f8QVquFX36o=", "requires": { "nan": "2.4.0", - "node-pre-gyp": "0.6.31" - }, - "dependencies": { - "node-pre-gyp": { - "version": "0.6.31", - "bundled": true, - "requires": { - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.0.0", - "rc": "1.1.6", - "request": "2.76.0", - "rimraf": "2.5.4", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.3.0" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true - } - } - }, - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1.0.9" - }, - "dependencies": { - "abbrev": { - "version": "1.0.9", - "bundled": true - } - } - }, - "npmlog": { - "version": "4.0.0", - "bundled": true, - "requires": { - "are-we-there-yet": "1.1.2", - "console-control-strings": "1.1.0", - "gauge": "2.6.0", - "set-blocking": "2.0.0" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.2", - "bundled": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.1.5" - }, - "dependencies": { - "delegates": { - "version": "1.0.0", - "bundled": true - }, - "readable-stream": { - "version": "2.1.5", - "bundled": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - }, - "dependencies": { - "buffer-shims": { - "version": "1.0.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "gauge": { - "version": "2.6.0", - "bundled": true, - "requires": { - "aproba": "1.0.4", - "console-control-strings": "1.1.0", - "has-color": "0.1.7", - "has-unicode": "2.0.1", - "object-assign": "4.1.0", - "signal-exit": "3.0.1", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.0" - }, - "dependencies": { - "aproba": { - "version": "1.0.4", - "bundled": true - }, - "has-color": { - "version": "0.1.7", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "object-assign": { - "version": "4.1.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.1", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.0.1", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.0.1", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "bundled": true - } - } - }, - "wide-align": { - "version": "1.1.0", - "bundled": true, - "requires": { - "string-width": "1.0.2" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - } - } - }, - "rc": { - "version": "1.1.6", - "bundled": true, - "requires": { - "deep-extend": "0.4.1", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "1.0.4" - }, - "dependencies": { - "deep-extend": { - "version": "0.4.1", - "bundled": true - }, - "ini": { - "version": "1.3.4", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "1.0.4", - "bundled": true - } - } - }, - "request": { - "version": "2.76.0", - "bundled": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.5.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.0", - "forever-agent": "0.6.1", - "form-data": "2.1.1", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.12", - "node-uuid": "1.4.7", - "oauth-sign": "0.8.2", - "qs": "6.3.0", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.4.3" - }, - "dependencies": { - "aws-sign2": { - "version": "0.6.0", - "bundled": true - }, - "aws4": { - "version": "1.5.0", - "bundled": true - }, - "caseless": { - "version": "0.11.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - }, - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.0", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.1.1", - "bundled": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.12" - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "bundled": true - } - } - }, - "har-validator": { - "version": "2.0.6", - "bundled": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.9.0", - "is-my-json-valid": "2.15.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "bundled": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "bundled": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "has-ansi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "ansi-regex": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "bundled": true - } - } - }, - "supports-color": { - "version": "2.0.0", - "bundled": true - } - } - }, - "commander": { - "version": "2.9.0", - "bundled": true, - "requires": { - "graceful-readlink": "1.0.1" - }, - "dependencies": { - "graceful-readlink": { - "version": "1.0.1", - "bundled": true - } - } - }, - "is-my-json-valid": { - "version": "2.15.0", - "bundled": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.0", - "xtend": "4.0.1" - }, - "dependencies": { - "generate-function": { - "version": "2.0.0", - "bundled": true - }, - "generate-object-property": { - "version": "1.2.0", - "bundled": true, - "requires": { - "is-property": "1.0.2" - }, - "dependencies": { - "is-property": { - "version": "1.0.2", - "bundled": true - } - } - }, - "jsonpointer": { - "version": "4.0.0", - "bundled": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - }, - "pinkie-promise": { - "version": "2.0.1", - "bundled": true, - "requires": { - "pinkie": "2.0.4" - }, - "dependencies": { - "pinkie": { - "version": "2.0.4", - "bundled": true - } - } - } - } - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - }, - "dependencies": { - "boom": { - "version": "2.10.1", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "requires": { - "boom": "2.10.1" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - } - } - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.3.1", - "sshpk": "1.10.1" - }, - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "bundled": true - }, - "jsprim": { - "version": "1.3.1", - "bundled": true, - "requires": { - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "extsprintf": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "requires": { - "extsprintf": "1.0.2" - } - } - } - }, - "sshpk": { - "version": "1.10.1", - "bundled": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.0", - "dashdash": "1.14.0", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.6", - "jodid25519": "1.0.2", - "jsbn": "0.1.0", - "tweetnacl": "0.14.3" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "bundled": true - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.0", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.3" - } - }, - "dashdash": { - "version": "1.14.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.0" - } - }, - "getpass": { - "version": "0.1.6", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.0" - } - }, - "jsbn": { - "version": "0.1.0", - "bundled": true, - "optional": true - }, - "tweetnacl": { - "version": "0.14.3", - "bundled": true, - "optional": true - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "mime-types": { - "version": "2.1.12", - "bundled": true, - "requires": { - "mime-db": "1.24.0" - }, - "dependencies": { - "mime-db": { - "version": "1.24.0", - "bundled": true - } - } - }, - "node-uuid": { - "version": "1.4.7", - "bundled": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true - }, - "qs": { - "version": "6.3.0", - "bundled": true - }, - "stringstream": { - "version": "0.0.5", - "bundled": true - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "requires": { - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "bundled": true - } - } - }, - "tunnel-agent": { - "version": "0.4.3", - "bundled": true - } - } - }, - "rimraf": { - "version": "2.5.4", - "bundled": true, - "requires": { - "glob": "7.1.1" - }, - "dependencies": { - "glob": { - "version": "7.1.1", - "bundled": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.3", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - }, - "dependencies": { - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - }, - "dependencies": { - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "minimatch": { - "version": "3.0.3", - "bundled": true, - "requires": { - "brace-expansion": "1.1.6" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.6", - "bundled": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - }, - "dependencies": { - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "semver": { - "version": "5.3.0", - "bundled": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.10", - "inherits": "2.0.3" - }, - "dependencies": { - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - }, - "fstream": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "4.1.9", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.5.4" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.9", - "bundled": true - } - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - } - } - }, - "tar-pack": { - "version": "3.3.0", - "bundled": true, - "requires": { - "debug": "2.2.0", - "fstream": "1.0.10", - "fstream-ignore": "1.0.5", - "once": "1.3.3", - "readable-stream": "2.1.5", - "rimraf": "2.5.4", - "tar": "2.2.1", - "uid-number": "0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "bundled": true, - "requires": { - "ms": "0.7.1" - }, - "dependencies": { - "ms": { - "version": "0.7.1", - "bundled": true - } - } - }, - "fstream": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "4.1.9", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.5.4" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.9", - "bundled": true - }, - "inherits": { - "version": "2.0.3", - "bundled": true - } - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "requires": { - "fstream": "1.0.10", - "inherits": "2.0.3", - "minimatch": "3.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "minimatch": { - "version": "3.0.3", - "bundled": true, - "requires": { - "brace-expansion": "1.1.6" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.6", - "bundled": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - } - } - }, - "once": { - "version": "1.3.3", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - }, - "dependencies": { - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, - "readable-stream": { - "version": "2.1.5", - "bundled": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - }, - "dependencies": { - "buffer-shims": { - "version": "1.0.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } - } - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - } - } - } - } - } + "node-pre-gyp": "0.6.39" } }, "sqlstring": { @@ -3577,6 +2943,11 @@ } } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", @@ -3592,14 +2963,6 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -3610,6 +2973,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -3666,6 +3037,31 @@ "random-js": "1.0.8" } }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", + "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", + "requires": { + "debug": "2.6.7", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, "tar-stream": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", @@ -3848,6 +3244,11 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, "uid-safe": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", @@ -4001,6 +3402,14 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "1.0.2" + } + }, "win-spawn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/win-spawn/-/win-spawn-2.0.0.tgz", @@ -4011,6 +3420,19 @@ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" }, + "winston": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", + "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "stack-trace": "0.0.10" + } + }, "wkx": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.2.0.tgz", diff --git a/package.json b/package.json index e843190..78a2b8a 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "homepage": "https://github.com/syzoj/syzoj#readme", "dependencies": { + "amqplib": "^0.5.2", "ansi-to-html": "^0.4.2", "async-lock": "^0.3.9", "body-parser": "^1.15.2", @@ -42,6 +43,7 @@ "jsonwebtoken": "^7.4.3", "moemark-renderer": "^1.2.6", "moment": "^2.15.0", + "msgpack-lite": "^0.1.26", "multer": "^1.2.0", "mysql": "^2.11.1", "node-7z": "^0.4.0", @@ -57,6 +59,7 @@ "syzoj-divine": "^1.0.2", "tmp-promise": "^1.0.3", "waliyun": "^3.1.1", + "winston": "^2.3.1", "xss": "^0.3.3" } } From f149f5656b1ab85625af8f91d9c8c5b35d7cfee4 Mon Sep 17 00:00:00 2001 From: hewenyang Date: Tue, 13 Feb 2018 17:50:02 +0800 Subject: [PATCH 2/7] Handle finished judge reports at web side --- libs/judgeResult.js | 78 +++++++++++++++++++++++++++++++++++++++ libs/judger.js | 51 ++++++++++++++++++++++--- libs/judger_interfaces.js | 53 ++++++++++++++++++++++++++ modules/api_v2.js | 49 ------------------------ modules/winston.js | 23 ++++++++++++ 5 files changed, 199 insertions(+), 55 deletions(-) create mode 100644 libs/judgeResult.js create mode 100644 libs/judger_interfaces.js create mode 100644 modules/winston.js diff --git a/libs/judgeResult.js b/libs/judgeResult.js new file mode 100644 index 0000000..88959cf --- /dev/null +++ b/libs/judgeResult.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const _ = require("lodash"); +const winston = require("winston"); +const interfaces_1 = require("./judger_interfaces"); +const compileError = "Compile Error", systemError = "System Error", testdataError = "No Testdata"; +exports.statusToString = {}; +exports.statusToString[interfaces_1.TestcaseResultType.Accepted] = "Accepted"; +exports.statusToString[interfaces_1.TestcaseResultType.WrongAnswer] = "Wrong Answer"; +exports.statusToString[interfaces_1.TestcaseResultType.PartiallyCorrect] = "Partially Correct"; +exports.statusToString[interfaces_1.TestcaseResultType.MemoryLimitExceeded] = "Memory Limit Exceeded"; +exports.statusToString[interfaces_1.TestcaseResultType.TimeLimitExceeded] = "Time Limit Exceeded"; +exports.statusToString[interfaces_1.TestcaseResultType.OutputLimitExceeded] = "Output Limit Exceeded"; +exports.statusToString[interfaces_1.TestcaseResultType.RuntimeError] = "Runtime Error"; +exports.statusToString[interfaces_1.TestcaseResultType.FileError] = "File Error"; +exports.statusToString[interfaces_1.TestcaseResultType.JudgementFailed] = "Judgement Failed"; +exports.statusToString[interfaces_1.TestcaseResultType.InvalidInteraction] = "Invalid Interaction"; +function firstNonAC(t) { + if (t.every(v => v === interfaces_1.TestcaseResultType.Accepted)) { + return interfaces_1.TestcaseResultType.Accepted; + } + else { + return t.find(r => r !== interfaces_1.TestcaseResultType.Accepted); + } +} +exports.firstNonAC = firstNonAC; +function convertResult(taskId, source) { + winston.debug(`Converting result for ${taskId}`, source); + let time = null, memory = null, score = null, done = true, statusString = null; + if (source.compile && source.compile.status === interfaces_1.TaskStatus.Failed) { + statusString = compileError; + } + else if (source.error != null) { + done = false; + if (source.error === interfaces_1.ErrorType.TestDataError) { + statusString = testdataError; + } + else { + statusString = systemError; + } + } + else if (source.judge != null && source.judge.subtasks != null) { + const forEveryTestcase = function (map, reduce) { + const list = source.judge.subtasks.map(s => reduce(s.cases.filter(c => c.result != null).map(c => map(c.result)))); + if (list.every(x => x == null)) + return null; + else + return reduce(list); + }; + time = forEveryTestcase(c => c.time, _.sum); + memory = forEveryTestcase(c => c.memory, _.max); + if (source.judge.subtasks.some(s => s.cases.some(c => c.status === interfaces_1.TaskStatus.Failed))) { + winston.debug(`Some subtasks failed, returning system error`); + statusString = systemError; + } + else { + score = _.sum(source.judge.subtasks.map(s => s.score)); + const finalResult = forEveryTestcase(c => c.type, firstNonAC); + statusString = exports.statusToString[finalResult]; + } + } + else { + statusString = systemError; + } + const result = { + taskId: taskId, + time: time, + memory: memory, + score: score, + statusNumber: done ? interfaces_1.TaskStatus.Done : interfaces_1.TaskStatus.Failed, + statusString: statusString, + result: source + }; + winston.debug(`Result for ${taskId}`, result); + return result; +} +exports.convertResult = convertResult; +//# sourceMappingURL=judgeResult.js.map diff --git a/libs/judger.js b/libs/judger.js index 85b40e5..b5ed963 100644 --- a/libs/judger.js +++ b/libs/judger.js @@ -6,29 +6,68 @@ const amqp = require('amqplib'); const util = require('util'); const winston = require('winston'); const msgPack = require('msgpack-lite'); +const interface = require('./judger_interfaces'); +const judgeResult = require('./judgeResult'); let amqpConnection; -let publicChannel; +let amqpSendChannel; +let amqpConsumeChannel; async function connect () { amqpConnection = await amqp.connect(syzoj.config.rabbitMQ); - publicChannel = await amqpConnection.createChannel(); - await publicChannel.assertQueue('judge', { + amqpSendChannel = await amqpConnection.createChannel(); + await amqpSendChannel.assertQueue('judge', { maxPriority: 5, durable: true }); - await publicChannel.assertQueue('result', { + await amqpSendChannel.assertQueue('result', { durable: true }); - await publicChannel.assertExchange('progress', 'fanout', { + await amqpSendChannel.assertExchange('progress', 'fanout', { durable: false }); + amqpConsumeChannel = await amqpConnection.createChannel(); + amqpConsumeChannel.prefetch(1); + winston.debug('Winston test'); + amqpConsumeChannel.consume('result', async (msg) => { + (async(msg) => { + const data = msgPack.decode(msg.content); + winston.verbose('Received report for task ' + data.taskId); + let JudgeState = syzoj.model('judge_state'); + let judge_state = await JudgeState.findOne({ where: { task_id: data.taskId } }); + if(data.type === interface.ProgressReportType.Finished) { + const convertedResult = judgeResult.convertResult(data.taskId, data.progress); + winston.verbose('Reporting report finished: ' + data.taskId); + const payload = msgPack.encode({ type: interface.ProgressReportType.Reported, taskId: data.taskId }); + amqpSendChannel.publish('progress', '', payload); + if(!judge_state) return; + judge_state.score = convertedResult.score; + judge_state.pending = false; + judge_state.status = convertedResult.statusString; + judge_state.total_time = convertedResult.time; + judge_state.max_memory = convertedResult.memory; + judge_state.result = convertedResult.result; + await judge_state.save(); + await judge_state.updateRelatedInfo(); + } else { + if(!judge_state) return; + judge_state.compilation = data.progress; + await judge_state.save(); + } + })(msg).then(async() => { + amqpConsumeChannel.ack(msg) + }, async(err) => { + winston.error('Error handling report', err); + amqpConsumeChannel.nack(msg, false, false); + }); + }); amqpConnection.on('error', (err) => { winston.error('RabbitMQ connection failure: ${err.toString()}'); amqpConnection.close(); process.exit(1); }); } + module.exports.judge = async function (judge_state, problem, priority) { let type, param, extraFile = null; switch (problem.type) { @@ -71,7 +110,7 @@ module.exports.judge = async function (judge_state, problem, priority) { }; // TODO: parse extraFileLocation - publicChannel.sendToQueue('judge', msgPack.encode({ content: req.content, extraData: null }), { priority: priority }); + amqpSendChannel.sendToQueue('judge', msgPack.encode({ content: req.content, extraData: null }), { priority: priority }); } connect(); diff --git a/libs/judger_interfaces.js b/libs/judger_interfaces.js new file mode 100644 index 0000000..a463f1a --- /dev/null +++ b/libs/judger_interfaces.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var RPCTaskType; +(function (RPCTaskType) { + RPCTaskType[RPCTaskType["Compile"] = 1] = "Compile"; + RPCTaskType[RPCTaskType["RunStandard"] = 2] = "RunStandard"; + RPCTaskType[RPCTaskType["RunSubmitAnswer"] = 3] = "RunSubmitAnswer"; + RPCTaskType[RPCTaskType["RunInteraction"] = 4] = "RunInteraction"; +})(RPCTaskType = exports.RPCTaskType || (exports.RPCTaskType = {})); +; +var ErrorType; +(function (ErrorType) { + ErrorType[ErrorType["SystemError"] = 0] = "SystemError"; + ErrorType[ErrorType["TestDataError"] = 1] = "TestDataError"; +})(ErrorType = exports.ErrorType || (exports.ErrorType = {})); +var TaskStatus; +(function (TaskStatus) { + TaskStatus[TaskStatus["Waiting"] = 0] = "Waiting"; + TaskStatus[TaskStatus["Running"] = 1] = "Running"; + TaskStatus[TaskStatus["Done"] = 2] = "Done"; + TaskStatus[TaskStatus["Failed"] = 3] = "Failed"; + TaskStatus[TaskStatus["Skipped"] = 4] = "Skipped"; +})(TaskStatus = exports.TaskStatus || (exports.TaskStatus = {})); +var TestcaseResultType; +(function (TestcaseResultType) { + TestcaseResultType[TestcaseResultType["Accepted"] = 1] = "Accepted"; + TestcaseResultType[TestcaseResultType["WrongAnswer"] = 2] = "WrongAnswer"; + TestcaseResultType[TestcaseResultType["PartiallyCorrect"] = 3] = "PartiallyCorrect"; + TestcaseResultType[TestcaseResultType["MemoryLimitExceeded"] = 4] = "MemoryLimitExceeded"; + TestcaseResultType[TestcaseResultType["TimeLimitExceeded"] = 5] = "TimeLimitExceeded"; + TestcaseResultType[TestcaseResultType["OutputLimitExceeded"] = 6] = "OutputLimitExceeded"; + TestcaseResultType[TestcaseResultType["FileError"] = 7] = "FileError"; + TestcaseResultType[TestcaseResultType["RuntimeError"] = 8] = "RuntimeError"; + TestcaseResultType[TestcaseResultType["JudgementFailed"] = 9] = "JudgementFailed"; + TestcaseResultType[TestcaseResultType["InvalidInteraction"] = 10] = "InvalidInteraction"; +})(TestcaseResultType = exports.TestcaseResultType || (exports.TestcaseResultType = {})); +var RPCReplyType; +(function (RPCReplyType) { + RPCReplyType[RPCReplyType["Started"] = 1] = "Started"; + RPCReplyType[RPCReplyType["Finished"] = 2] = "Finished"; + RPCReplyType[RPCReplyType["Error"] = 3] = "Error"; +})(RPCReplyType = exports.RPCReplyType || (exports.RPCReplyType = {})); +var ProgressReportType; +(function (ProgressReportType) { + ProgressReportType[ProgressReportType["Started"] = 1] = "Started"; + ProgressReportType[ProgressReportType["Compiled"] = 2] = "Compiled"; + ProgressReportType[ProgressReportType["Progress"] = 3] = "Progress"; + ProgressReportType[ProgressReportType["Finished"] = 4] = "Finished"; + ProgressReportType[ProgressReportType["Reported"] = 5] = "Reported"; +})(ProgressReportType = exports.ProgressReportType || (exports.ProgressReportType = {})); +exports.redisBinarySuffix = '-bin'; +exports.redisMetadataSuffix = '-meta'; +//# sourceMappingURL=interfaces.js.map \ No newline at end of file diff --git a/modules/api_v2.js b/modules/api_v2.js index 3dd25de..3819433 100644 --- a/modules/api_v2.js +++ b/modules/api_v2.js @@ -111,52 +111,3 @@ app.apiRouter.post('/api/v2/markdown', async (req, res) => { res.send(e); } }); - -app.apiRouter.post('/api/v2/judge/compiled', async (req, res) => { - try { - if (req.get('Token') !== syzoj.config.judge_token) return res.status(403).send({ err: 'Incorrect token' }); - let data = req.body; - - let JudgeState = syzoj.model('judge_state'); - let judge_state = await JudgeState.findOne({ where: { task_id: req.body.taskId } }); - if (!judge_state) { - res.send({ return: 1 }); // The task might have been rejudging. - return; - } - judge_state.compilation = req.body.result; - await judge_state.save(); - - res.send({ return: 0 }); - } catch (e) { - syzoj.log(e); - res.status(500).send(e); - } -}); - -app.apiRouter.post('/api/v2/judge/finished', async (req, res) => { - try { - if (req.get('Token') !== syzoj.config.judge_token) return res.status(403).send({ err: 'Incorrect token' }); - let data = req.body; - - let JudgeState = syzoj.model('judge_state'); - let judge_state = await JudgeState.findOne({ where: { task_id: req.body.taskId } }); - if (!judge_state) { - res.send({ return: 1 }); // The task might have been rejudging. - return; - } - // await judge_state.updateResult(JSON.parse(req.body)); - judge_state.score = data.score; - judge_state.pending = false; - judge_state.status = data.statusString; - judge_state.total_time = data.time; - judge_state.max_memory = data.memory; - judge_state.result = data.result; - await judge_state.save(); - await judge_state.updateRelatedInfo(); - - res.send({ return: 0 }); - } catch (e) { - syzoj.log(e); - res.status(500).send(e); - } -}); diff --git a/modules/winston.js b/modules/winston.js new file mode 100644 index 0000000..4849203 --- /dev/null +++ b/modules/winston.js @@ -0,0 +1,23 @@ +const winston = require('winston'); +const _ = require('lodash'); +const util = require('util'); + +function formatter(args) { + var msg = args.level + ' - ' + args.message + (_.isEmpty(args.meta) ? '' : (' - ' + util.inspect(args.meta))); + return msg; +} + +function configureWinston(verbose) { + winston.configure({ + transports: [ + new (winston.transports.Console)({ formatter: formatter }) + ] + }); + if (verbose) { + winston.level = 'debug'; + } else { + winston.level = 'info'; + } +} + +configureWinston(false); From 9eeb1fde5d9ee8e81021bd230fe480055c0fde11 Mon Sep 17 00:00:00 2001 From: hewenyang Date: Tue, 13 Feb 2018 21:06:16 +0800 Subject: [PATCH 3/7] Implement judge status tracking --- app.js | 6 +- libs/judger.js | 32 +++- {modules => libs}/winston.js | 2 +- modules/socketio.js | 298 ++++++++++++++++++++++++++++++++ package-lock.json | 324 +++++++++++++++++++++++++++++++++++ package.json | 2 + views/submission.ejs | 4 +- 7 files changed, 663 insertions(+), 5 deletions(-) rename {modules => libs}/winston.js (91%) create mode 100644 modules/socketio.js diff --git a/app.js b/app.js index a91284a..fe2b9f8 100644 --- a/app.js +++ b/app.js @@ -39,12 +39,16 @@ global.syzoj = { console.log(obj); }, async run() { + let winstonLib = require('./libs/winston'); + winstonLib.configureWinston(true); + let Express = require('express'); global.app = Express(); syzoj.production = app.get('env') === 'production'; - app.listen(parseInt(syzoj.config.port), syzoj.config.hostname, () => { + app.server = require('http').createServer(app); + app.server.listen(parseInt(syzoj.config.port), syzoj.config.hostname, () => { this.log(`SYZOJ is listening on ${syzoj.config.hostname}:${parseInt(syzoj.config.port)}...`); }); diff --git a/libs/judger.js b/libs/judger.js index b5ed963..cb4a67b 100644 --- a/libs/judger.js +++ b/libs/judger.js @@ -49,10 +49,12 @@ async function connect () { judge_state.result = convertedResult.result; await judge_state.save(); await judge_state.updateRelatedInfo(); - } else { + } else if(data.type == interface.ProgressReportType.Compiled) { if(!judge_state) return; judge_state.compilation = data.progress; await judge_state.save(); + } else { + winston.error("Unsupported result type: " + data.type); } })(msg).then(async() => { amqpConsumeChannel.ack(msg) @@ -61,6 +63,34 @@ async function connect () { amqpConsumeChannel.nack(msg, false, false); }); }); + socketio = require('../modules/socketio'); + const progressChannel = await amqpConnection.createChannel(); + const queueName = (await progressChannel.assertQueue('', { exclusive: true })).queue; + await progressChannel.bindQueue(queueName, 'progress', ''); + await progressChannel.consume(queueName, (msg) => { + const data = msgPack.decode(msg.content); + winston.verbose(`Got result from progress exchange, id: ${data.taskId}`); + + (async (result) => { + if (result.type === interface.ProgressReportType.Started) { + socketio.createTask(result.taskId); + } else if (result.type === interface.ProgressReportType.Compiled) { + socketio.updateCompileStatus(result.taskId, result.progress); + } else if (result.type === interface.ProgressReportType.Progress) { + socketio.updateProgress(result.taskId, result.progress); + } else if (result.type === interface.ProgressReportType.Finished) { + socketio.updateResult(result.taskId, result.progress); + } else if (result.type === interface.ProgressReportType.Reported) { + socketio.cleanupProgress(result.taskId); + } + })(data).then(async() => { + progressChannel.ack(msg) + }, async(err) => { + winston.error('Error handling progress', err); + progressChannel.nack(msg, false, false); + }); + }); + winston.debug('Created progress exchange queue', queueName); amqpConnection.on('error', (err) => { winston.error('RabbitMQ connection failure: ${err.toString()}'); amqpConnection.close(); diff --git a/modules/winston.js b/libs/winston.js similarity index 91% rename from modules/winston.js rename to libs/winston.js index 4849203..dfd668a 100644 --- a/modules/winston.js +++ b/libs/winston.js @@ -20,4 +20,4 @@ function configureWinston(verbose) { } } -configureWinston(false); +module.exports.configureWinston = configureWinston; diff --git a/modules/socketio.js b/modules/socketio.js new file mode 100644 index 0000000..bced125 --- /dev/null +++ b/modules/socketio.js @@ -0,0 +1,298 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const socketio = require("socket.io"); +const diff = require("jsondiffpatch"); +const jwt = require("jsonwebtoken"); +const winston = require("winston"); +const judgeResult_1 = require("../libs/judgeResult"); +const interfaces_1 = require("../libs/judger_interfaces"); +let ioInstance; +let detailProgressNamespace; +let roughProgressNamespace; +let compileProgressNamespace; +const currentJudgeList = {}; +const finishedJudgeList = {}; +const compiledList = []; +const clientDetailProgressList = {}; +const clientDisplayConfigList = {}; + +function processOverallResult(source, config) { + if (source == null) + return null; + if (source.error != null) { + return { + error: source.error, + systemMessage: source.systemMessage + }; + } + return { + compile: source.compile, + judge: config.showDetailResult ? (source.judge && { + subtasks: source.judge.subtasks && source.judge.subtasks.map(st => ({ + score: st.score, + cases: st.cases.map(cs => ({ + status: cs.status, + result: cs.result && { + type: cs.result.type, + time: config.showUsage ? cs.result.time : undefined, + memory: config.showUsage ? cs.result.memory : undefined, + scoringRate: cs.result.scoringRate, + systemMessage: cs.result.systemMessage, + input: config.showTestdata ? cs.result.input : undefined, + output: config.showTestdata ? cs.result.output : undefined, + userOutput: config.showTestdata ? cs.result.userOutput : undefined, + userError: config.showTestdata ? cs.result.userError : undefined, + spjMessage: config.showTestdata ? cs.result.spjMessage : undefined, + } + })) + })) + }) : null + }; +} +function getCompileStatus(status) { + if (["System Error", "Compile Error", "No Testdata"].includes(status)) { + return status; + } + else { + return "Submitted"; + } +} +function processRoughResult(source, config) { + const result = config.showResult ? + source.result : + getCompileStatus(source.result); + return { + result: result, + time: config.showUsage ? source.time : null, + memory: config.showUsage ? source.memory : null, + score: config.showScore ? source.score : null + }; +} +function forAllClients(ns, taskId, exec) { + ns.in(taskId.toString()).clients((err, clients) => { + if (!err) { + clients.forEach(client => { + exec(client); + }); + } + else { + winston.warn(`Error while listing socketio clients in ${taskId}`, err); + } + }); +} +function initializeSocketIO(s) { + ioInstance = socketio(s); + const initializeNamespace = (name, exec) => { + winston.debug('initializing socketIO', name); + const newNamespace = ioInstance.of('/' + name); + newNamespace.on('connection', (socket) => { + socket.on('disconnect', () => { + winston.info(`Client ${socket.id} disconnected.`); + delete clientDisplayConfigList[socket.id]; + if (clientDetailProgressList[socket.id]) { + delete clientDetailProgressList[socket.id]; + } + }); + socket.on('join', (reqJwt, cb) => { + winston.info(`Client ${socket.id} connected.`); + let req; + try { + req = jwt.verify(reqJwt, syzoj.config.judge_token); + if (req.type !== name) { + throw new Error("Request type in token mismatch."); + } + clientDisplayConfigList[socket.id] = req.displayConfig; + const taskId = req.taskId; + winston.verbose(`A client trying to join ${name} namespace for ${taskId}.`); + socket.join(taskId.toString()); + exec(req, socket).then(x => cb(x), err => cb({ ok: false, message: err.toString() })); + } + catch (err) { + winston.info('Error while joining.'); + cb({ + ok: false, + message: err.toString() + }); + return; + } + }); + }); + return newNamespace; + }; + detailProgressNamespace = initializeNamespace('detail', async (req, socket) => { + const taskId = req.taskId; + if (finishedJudgeList[taskId]) { + winston.debug(`Judge task #${taskId} has been finished, ${JSON.stringify(currentJudgeList[taskId])}`); + return { + ok: true, + running: false, + finished: true, + result: processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[socket.id]), + roughResult: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[socket.id]) + }; + } + else { + winston.debug(`Judge task #${taskId} has not been finished`); + if (currentJudgeList[taskId]) { + clientDetailProgressList[socket.id] = { + version: 0, + content: processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[socket.id]) + }; + return { + ok: true, + finished: false, + running: true, + current: clientDetailProgressList[socket.id] + }; + } + else { + return { + ok: true, + finished: false, + running: false + }; + } + } + }); + roughProgressNamespace = initializeNamespace('rough', async (req, socket) => { + const taskId = req.taskId; + if (finishedJudgeList[taskId]) { + return { + ok: true, + running: false, + finished: true, + result: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[socket.id]) + }; + } + else if (currentJudgeList[taskId]) { + return { + ok: true, + running: true, + finished: false + }; + } + else { + return { + ok: true, + running: false, + finished: false + }; + } + }); + compileProgressNamespace = initializeNamespace('compile', async (req, socket) => { + const taskId = req.taskId; + if (compiledList[taskId]) { + return { + ok: true, + running: false, + finished: true, + result: compiledList[taskId] + }; + } + else if (currentJudgeList[taskId]) { + return { + ok: true, + running: true, + finished: false + }; + } + else { + return { + ok: true, + running: false, + finished: false + }; + } + }); +} +exports.initializeSocketIO = initializeSocketIO; +function createTask(taskId) { + winston.debug(`Judge task #${taskId} has started`); + currentJudgeList[taskId] = {}; + finishedJudgeList[taskId] = null; + forAllClients(detailProgressNamespace, taskId, (clientId) => { + clientDetailProgressList[clientId] = { + version: 0, + content: {} + }; + }); + roughProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); + detailProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); + compileProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); +} +exports.createTask = createTask; +function updateCompileStatus(taskId, result) { + winston.debug(`Updating compilation status for #${taskId}`); + compiledList[taskId] = { result: result.status === interfaces_1.TaskStatus.Done ? 'Submitted' : 'Compile Error' }; + compileProgressNamespace.to(taskId.toString()).emit('finish', { + taskId: taskId, + result: compiledList[taskId] + }); +} +exports.updateCompileStatus = updateCompileStatus; +function updateProgress(taskId, data) { + winston.verbose(`Updating progress for #${taskId}`); + currentJudgeList[taskId] = data; + forAllClients(detailProgressNamespace, taskId, (client) => { + winston.debug(`Pushing progress update to ${client}`); + if (clientDetailProgressList[client] && clientDisplayConfigList[client]) { + const original = clientDetailProgressList[client].content; + const updated = processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[client]); + const version = clientDetailProgressList[client].version; + detailProgressNamespace.sockets[client].emit('update', { + taskId: taskId, + from: version, + to: version + 1, + delta: diff.diff(original, updated) + }); + clientDetailProgressList[client].version++; + } + }); +} +exports.updateProgress = updateProgress; +function updateResult(taskId, data) { + currentJudgeList[taskId] = data; + if (compiledList[taskId] == null) { + if (data.error != null) { + compiledList[taskId] = { result: "System Error" }; + compileProgressNamespace.to(taskId.toString()).emit('finish', { + taskId: taskId, + result: compiledList[taskId] + }); + } + } + const finalResult = judgeResult_1.convertResult(taskId, data); + const roughResult = { + result: finalResult.statusString, + time: finalResult.time, + memory: finalResult.memory, + score: finalResult.score + }; + finishedJudgeList[taskId] = roughResult; + forAllClients(roughProgressNamespace, taskId, (client) => { + winston.debug(`Pushing rough result to ${client}`); + roughProgressNamespace.sockets[client].emit('finish', { + taskId: taskId, + result: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[client]) + }); + }); + forAllClients(detailProgressNamespace, taskId, (client) => { + if (clientDisplayConfigList[client]) { + winston.debug(`Pushing detail result to ${client}`); + detailProgressNamespace.sockets[client].emit('finish', { + taskId: taskId, + result: processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[client]), + roughResult: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[client]) + }); + delete clientDetailProgressList[client]; + } + }); +} +exports.updateResult = updateResult; +function cleanupProgress(taskId) { + setTimeout(() => { delete currentJudgeList[taskId]; }, 10000); +} +exports.cleanupProgress = cleanupProgress; +//# sourceMappingURL=socketio.js.map + +initializeSocketIO(app.server); diff --git a/package-lock.json b/package-lock.json index 41b2295..9ccd318 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,11 @@ "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=" }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -106,6 +111,11 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" + }, "ansi-to-html": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.4.2.tgz", @@ -164,6 +174,11 @@ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", @@ -179,6 +194,11 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, "async-lock": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-0.3.10.tgz", @@ -202,6 +222,11 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, "bagpipe": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", @@ -212,11 +237,21 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, "base64-js": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, "base64url": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", @@ -231,6 +266,14 @@ "tweetnacl": "0.14.5" } }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, "bignumber.js": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.1.2.tgz", @@ -252,6 +295,11 @@ "readable-stream": "2.3.3" } }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -406,6 +454,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", @@ -430,6 +483,33 @@ "tunnel-agent": "0.4.3" } }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=" + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "requires": { + "ansi-regex": "0.2.1" + } + } + } + }, "cheerio": { "version": "1.0.0-rc.2", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", @@ -494,6 +574,21 @@ "graceful-readlink": "1.0.1" } }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -958,6 +1053,70 @@ "once": "1.4.0" } }, + "engine.io": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.4.tgz", + "integrity": "sha1-PQIRtwpVLOhB/8fahiezAamkFi4=", + "requires": { + "accepts": "1.3.3", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "2.6.9", + "engine.io-parser": "2.1.2", + "uws": "0.14.5", + "ws": "3.3.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.4.tgz", + "integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "2.6.9", + "engine.io-parser": "2.1.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "1.0.2" + } + }, "entities": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", @@ -1354,6 +1513,41 @@ "har-schema": "1.0.5" } }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "requires": { + "ansi-regex": "0.2.1" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=" + } + } + }, + "has-binary2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1442,6 +1636,11 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", @@ -1641,6 +1840,14 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "jsondiffpatch": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.2.4.tgz", + "integrity": "sha1-1LbFOz/H2htLkcHCrsi5MrdRHVw=", + "requires": { + "chalk": "0.5.1" + } + }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", @@ -2191,6 +2398,11 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, "object-keys": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", @@ -2273,6 +2485,22 @@ "@types/node": "6.0.83" } }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "1.0.2" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "1.0.2" + } + }, "parseurl": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", @@ -2864,6 +3092,61 @@ "hoek": "2.16.3" } }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "requires": { + "debug": "2.6.7", + "engine.io": "3.1.4", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.0.4", + "socket.io-parser": "3.1.2" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "2.6.7", + "engine.io-client": "3.1.4", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "3.1.2", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.2.tgz", + "integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=", + "requires": { + "component-emitter": "1.2.1", + "debug": "2.6.7", + "has-binary2": "1.0.2", + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", @@ -3023,6 +3306,11 @@ "escape-string-regexp": "1.0.5" } }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=" + }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", @@ -3167,6 +3455,11 @@ "tmp": "0.0.31" } }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, "topo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", @@ -3257,6 +3550,11 @@ "random-bytes": "1.0.0" } }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, "unbzip2-stream": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.4.tgz", @@ -3304,6 +3602,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" }, + "uws": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz", + "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", + "optional": true + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", @@ -3467,6 +3771,16 @@ "slide": "1.1.6" } }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" + } + }, "xml-mapping": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/xml-mapping/-/xml-mapping-1.7.1.tgz", @@ -3498,6 +3812,11 @@ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, "xpath": { "version": "0.0.24", "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.24.tgz", @@ -3575,6 +3894,11 @@ "buffer-crc32": "0.2.13", "fd-slicer": "1.0.1" } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" } } } diff --git a/package.json b/package.json index 78a2b8a..67c278d 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "fs-extra": "^4.0.1", "gravatar": "^1.5.2", "js-yaml": "^3.9.0", + "jsondiffpatch": "0.2.4", "jsonwebtoken": "^7.4.3", "moemark-renderer": "^1.2.6", "moment": "^2.15.0", @@ -55,6 +56,7 @@ "sendmail": "^1.1.1", "sequelize": "^3.24.3", "session-file-store": "^1.0.0", + "socket.io": "^2.0.3", "sqlite3": "^3.1.4", "syzoj-divine": "^1.0.2", "tmp-promise": "^1.0.3", diff --git a/views/submission.ejs b/views/submission.ejs index 13e2cd9..13fb3e7 100644 --- a/views/submission.ejs +++ b/views/submission.ejs @@ -108,7 +108,7 @@ Vue.component("code-box", { template: "#codeBoxTemplate", props: ['title', 'content', 'escape'], }); -const socketUrl = <%- syzoj.utils.judgeServer('detail') %>; +const socketUrl = "/detail"; const displayConfig = <%- JSON.stringify(displayConfig) %>; const token = <%- JSON.stringify(socketToken) %>; @@ -268,4 +268,4 @@ if (token != null) { } -<% include footer %> \ No newline at end of file +<% include footer %> From 641f94b0a06bfc83485919fe2287eced9ea08624 Mon Sep 17 00:00:00 2001 From: hewenyang Date: Tue, 13 Feb 2018 21:19:47 +0800 Subject: [PATCH 4/7] Remove external judge server entirely --- config-example.json | 2 -- views/submissions.ejs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/config-example.json b/config-example.json index c34c4f0..8f79a71 100644 --- a/config-example.json +++ b/config-example.json @@ -166,8 +166,6 @@ } ], "session_secret": "233", - "judge_server_addr": "http://127.0.0.1:5284", "rabbitMQ": "amqp://localhost/", - "judge_token": "233", "email_jwt_secret": "test" } diff --git a/views/submissions.ejs b/views/submissions.ejs index dd7b9a4..616164f 100644 --- a/views/submissions.ejs +++ b/views/submissions.ejs @@ -114,7 +114,7 @@ $(function () { $('#select_status').dropdown(); }); const itemList = <%- JSON.stringify(items) %>; -const socketUrl = <%- syzoj.utils.judgeServer(pushType) %>; +const socketUrl = "/rough"; const displayConfig = <%- JSON.stringify(displayConfig) %>; const vueApp = new Vue({ From 1244a8d7a1673a8a914d9d71b3aa3d94e48b68d2 Mon Sep 17 00:00:00 2001 From: hewenyang Date: Wed, 14 Feb 2018 09:55:13 +0800 Subject: [PATCH 5/7] Upload data for answer submission problems and fix some horrible mistakes --- config-example.json | 1 + libs/judger.js | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/config-example.json b/config-example.json index 8f79a71..e6d89cc 100644 --- a/config-example.json +++ b/config-example.json @@ -167,5 +167,6 @@ ], "session_secret": "233", "rabbitMQ": "amqp://localhost/", + "judge_token": "233", "email_jwt_secret": "test" } diff --git a/libs/judger.js b/libs/judger.js index cb4a67b..aef341f 100644 --- a/libs/judger.js +++ b/libs/judger.js @@ -28,7 +28,6 @@ async function connect () { }); amqpConsumeChannel = await amqpConnection.createChannel(); amqpConsumeChannel.prefetch(1); - winston.debug('Winston test'); amqpConsumeChannel.consume('result', async (msg) => { (async(msg) => { const data = msgPack.decode(msg.content); @@ -99,12 +98,13 @@ async function connect () { } module.exports.judge = async function (judge_state, problem, priority) { - let type, param, extraFile = null; + let type, param, extraData = null; switch (problem.type) { case 'submit-answer': type = enums.ProblemType.AnswerSubmission; param = null; - extraFile = 'static/uploads/answer/' + judge_state.code; + let fs = Promise.promisifyAll(require('fs-extra')); + extraData = await fs.readFileAsync(syzoj.model('file').resolvePath('answer', judge_state.code)); break; case 'interaction': type = enums.ProblemType.Interaction; @@ -128,19 +128,15 @@ module.exports.judge = async function (judge_state, problem, priority) { break; } - const req = { - content: { - taskId: judge_state.task_id, - testData: problem.id.toString(), - type: type, - priority: priority, - param: param - }, - extraFileLocation: extraFile + const content = { + taskId: judge_state.task_id, + testData: problem.id.toString(), + type: type, + priority: priority, + param: param }; - // TODO: parse extraFileLocation - amqpSendChannel.sendToQueue('judge', msgPack.encode({ content: req.content, extraData: null }), { priority: priority }); + amqpSendChannel.sendToQueue('judge', msgPack.encode({ content: content, extraData: extraData }), { priority: priority }); } connect(); From f1d29a04e678e90403e7c08f20d5ef9a6b079ab6 Mon Sep 17 00:00:00 2001 From: hewenyang Date: Wed, 14 Feb 2018 17:16:32 +0800 Subject: [PATCH 6/7] Some minor tweaks --- app.js | 6 +++--- libs/judgeResult.js | 36 ++++++++++++++++++------------------ libs/judger.js | 3 +-- modules/socketio.js | 8 ++++---- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/app.js b/app.js index fe2b9f8..9af6d40 100644 --- a/app.js +++ b/app.js @@ -39,13 +39,12 @@ global.syzoj = { console.log(obj); }, async run() { - let winstonLib = require('./libs/winston'); - winstonLib.configureWinston(true); - let Express = require('express'); global.app = Express(); syzoj.production = app.get('env') === 'production'; + let winstonLib = require('./libs/winston'); + winstonLib.configureWinston(!syzoj.production); app.server = require('http').createServer(app); app.server.listen(parseInt(syzoj.config.port), syzoj.config.hostname, () => { @@ -86,6 +85,7 @@ global.syzoj = { app.use(csurf({ cookie: true })); await this.connectDatabase(); + await this.lib('judger').connect(); this.loadModules(); }, async connectDatabase() { diff --git a/libs/judgeResult.js b/libs/judgeResult.js index 88959cf..ddd8197 100644 --- a/libs/judgeResult.js +++ b/libs/judgeResult.js @@ -2,37 +2,37 @@ Object.defineProperty(exports, "__esModule", { value: true }); const _ = require("lodash"); const winston = require("winston"); -const interfaces_1 = require("./judger_interfaces"); +const interfaces = require("./judger_interfaces"); const compileError = "Compile Error", systemError = "System Error", testdataError = "No Testdata"; exports.statusToString = {}; -exports.statusToString[interfaces_1.TestcaseResultType.Accepted] = "Accepted"; -exports.statusToString[interfaces_1.TestcaseResultType.WrongAnswer] = "Wrong Answer"; -exports.statusToString[interfaces_1.TestcaseResultType.PartiallyCorrect] = "Partially Correct"; -exports.statusToString[interfaces_1.TestcaseResultType.MemoryLimitExceeded] = "Memory Limit Exceeded"; -exports.statusToString[interfaces_1.TestcaseResultType.TimeLimitExceeded] = "Time Limit Exceeded"; -exports.statusToString[interfaces_1.TestcaseResultType.OutputLimitExceeded] = "Output Limit Exceeded"; -exports.statusToString[interfaces_1.TestcaseResultType.RuntimeError] = "Runtime Error"; -exports.statusToString[interfaces_1.TestcaseResultType.FileError] = "File Error"; -exports.statusToString[interfaces_1.TestcaseResultType.JudgementFailed] = "Judgement Failed"; -exports.statusToString[interfaces_1.TestcaseResultType.InvalidInteraction] = "Invalid Interaction"; +exports.statusToString[interfaces.TestcaseResultType.Accepted] = "Accepted"; +exports.statusToString[interfaces.TestcaseResultType.WrongAnswer] = "Wrong Answer"; +exports.statusToString[interfaces.TestcaseResultType.PartiallyCorrect] = "Partially Correct"; +exports.statusToString[interfaces.TestcaseResultType.MemoryLimitExceeded] = "Memory Limit Exceeded"; +exports.statusToString[interfaces.TestcaseResultType.TimeLimitExceeded] = "Time Limit Exceeded"; +exports.statusToString[interfaces.TestcaseResultType.OutputLimitExceeded] = "Output Limit Exceeded"; +exports.statusToString[interfaces.TestcaseResultType.RuntimeError] = "Runtime Error"; +exports.statusToString[interfaces.TestcaseResultType.FileError] = "File Error"; +exports.statusToString[interfaces.TestcaseResultType.JudgementFailed] = "Judgement Failed"; +exports.statusToString[interfaces.TestcaseResultType.InvalidInteraction] = "Invalid Interaction"; function firstNonAC(t) { - if (t.every(v => v === interfaces_1.TestcaseResultType.Accepted)) { - return interfaces_1.TestcaseResultType.Accepted; + if (t.every(v => v === interfaces.TestcaseResultType.Accepted)) { + return interfaces.TestcaseResultType.Accepted; } else { - return t.find(r => r !== interfaces_1.TestcaseResultType.Accepted); + return t.find(r => r !== interfaces.TestcaseResultType.Accepted); } } exports.firstNonAC = firstNonAC; function convertResult(taskId, source) { winston.debug(`Converting result for ${taskId}`, source); let time = null, memory = null, score = null, done = true, statusString = null; - if (source.compile && source.compile.status === interfaces_1.TaskStatus.Failed) { + if (source.compile && source.compile.status === interfaces.TaskStatus.Failed) { statusString = compileError; } else if (source.error != null) { done = false; - if (source.error === interfaces_1.ErrorType.TestDataError) { + if (source.error === interfaces.ErrorType.TestDataError) { statusString = testdataError; } else { @@ -49,7 +49,7 @@ function convertResult(taskId, source) { }; time = forEveryTestcase(c => c.time, _.sum); memory = forEveryTestcase(c => c.memory, _.max); - if (source.judge.subtasks.some(s => s.cases.some(c => c.status === interfaces_1.TaskStatus.Failed))) { + if (source.judge.subtasks.some(s => s.cases.some(c => c.status === interfaces.TaskStatus.Failed))) { winston.debug(`Some subtasks failed, returning system error`); statusString = systemError; } @@ -67,7 +67,7 @@ function convertResult(taskId, source) { time: time, memory: memory, score: score, - statusNumber: done ? interfaces_1.TaskStatus.Done : interfaces_1.TaskStatus.Failed, + statusNumber: done ? interfaces.TaskStatus.Done : interfaces.TaskStatus.Failed, statusString: statusString, result: source }; diff --git a/libs/judger.js b/libs/judger.js index aef341f..38cb20c 100644 --- a/libs/judger.js +++ b/libs/judger.js @@ -96,6 +96,7 @@ async function connect () { process.exit(1); }); } +module.exports.connect = connect; module.exports.judge = async function (judge_state, problem, priority) { let type, param, extraData = null; @@ -138,5 +139,3 @@ module.exports.judge = async function (judge_state, problem, priority) { amqpSendChannel.sendToQueue('judge', msgPack.encode({ content: content, extraData: extraData }), { priority: priority }); } - -connect(); diff --git a/modules/socketio.js b/modules/socketio.js index bced125..cd137c1 100644 --- a/modules/socketio.js +++ b/modules/socketio.js @@ -4,8 +4,8 @@ const socketio = require("socket.io"); const diff = require("jsondiffpatch"); const jwt = require("jsonwebtoken"); const winston = require("winston"); -const judgeResult_1 = require("../libs/judgeResult"); -const interfaces_1 = require("../libs/judger_interfaces"); +const judgeResult = require("../libs/judgeResult"); +const interfaces = require("../libs/judger_interfaces"); let ioInstance; let detailProgressNamespace; let roughProgressNamespace; @@ -223,7 +223,7 @@ function createTask(taskId) { exports.createTask = createTask; function updateCompileStatus(taskId, result) { winston.debug(`Updating compilation status for #${taskId}`); - compiledList[taskId] = { result: result.status === interfaces_1.TaskStatus.Done ? 'Submitted' : 'Compile Error' }; + compiledList[taskId] = { result: result.status === interfaces.TaskStatus.Done ? 'Submitted' : 'Compile Error' }; compileProgressNamespace.to(taskId.toString()).emit('finish', { taskId: taskId, result: compiledList[taskId] @@ -261,7 +261,7 @@ function updateResult(taskId, data) { }); } } - const finalResult = judgeResult_1.convertResult(taskId, data); + const finalResult = judgeResult.convertResult(taskId, data); const roughResult = { result: finalResult.statusString, time: finalResult.time, From 71605cb66ffea4c2291bf70bbb251f9199e9f460 Mon Sep 17 00:00:00 2001 From: hewenyang Date: Thu, 15 Feb 2018 00:35:40 +0800 Subject: [PATCH 7/7] Fix bug where skipped subtasks with NULL time & memory field cause total time to be NaN and fail to be written to database --- libs/judgeResult.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/judgeResult.js b/libs/judgeResult.js index ddd8197..96537e4 100644 --- a/libs/judgeResult.js +++ b/libs/judgeResult.js @@ -47,8 +47,8 @@ function convertResult(taskId, source) { else return reduce(list); }; - time = forEveryTestcase(c => c.time, _.sum); - memory = forEveryTestcase(c => c.memory, _.max); + time = forEveryTestcase(c => (c.time ? c.time : 0), _.sum); + memory = forEveryTestcase(c => (c.memory ? c.memory : 0), _.max); if (source.judge.subtasks.some(s => s.cases.some(c => c.status === interfaces.TaskStatus.Failed))) { winston.debug(`Some subtasks failed, returning system error`); statusString = systemError;