|
|
@ -2,6 +2,7 @@ let fs = require('fs'), |
|
|
|
path = require('path'), |
|
|
|
path = require('path'), |
|
|
|
util = require('util'); |
|
|
|
util = require('util'); |
|
|
|
const serializejs = require('serialize-javascript'); |
|
|
|
const serializejs = require('serialize-javascript'); |
|
|
|
|
|
|
|
const UUID = require('uuid'); |
|
|
|
|
|
|
|
|
|
|
|
const commandLineArgs = require('command-line-args'); |
|
|
|
const commandLineArgs = require('command-line-args'); |
|
|
|
const optionDefinitions = [ |
|
|
|
const optionDefinitions = [ |
|
|
@ -18,6 +19,7 @@ global.syzoj = { |
|
|
|
models: [], |
|
|
|
models: [], |
|
|
|
modules: [], |
|
|
|
modules: [], |
|
|
|
db: null, |
|
|
|
db: null, |
|
|
|
|
|
|
|
serviceID: UUID(), |
|
|
|
log(obj) { |
|
|
|
log(obj) { |
|
|
|
if (obj instanceof ErrorMessage) return; |
|
|
|
if (obj instanceof ErrorMessage) return; |
|
|
|
console.log(obj); |
|
|
|
console.log(obj); |
|
|
@ -38,15 +40,6 @@ global.syzoj = { |
|
|
|
let winstonLib = require('./libs/winston'); |
|
|
|
let winstonLib = require('./libs/winston'); |
|
|
|
winstonLib.configureWinston(!syzoj.production); |
|
|
|
winstonLib.configureWinston(!syzoj.production); |
|
|
|
|
|
|
|
|
|
|
|
app.server = require('http').createServer(app); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!module.parent) { |
|
|
|
|
|
|
|
// Loaded by `require()`, not node CLI.
|
|
|
|
|
|
|
|
app.server.listen(parseInt(syzoj.config.port), syzoj.config.hostname, () => { |
|
|
|
|
|
|
|
this.log(`SYZOJ is listening on ${syzoj.config.hostname}:${parseInt(syzoj.config.port)}...`); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set assets dir
|
|
|
|
// Set assets dir
|
|
|
|
app.use(Express.static(__dirname + '/static', { maxAge: syzoj.production ? '1y' : 0 })); |
|
|
|
app.use(Express.static(__dirname + '/static', { maxAge: syzoj.production ? '1y' : 0 })); |
|
|
|
|
|
|
|
|
|
|
@ -79,9 +72,7 @@ global.syzoj = { |
|
|
|
})()); |
|
|
|
})()); |
|
|
|
|
|
|
|
|
|
|
|
await this.connectDatabase(); |
|
|
|
await this.connectDatabase(); |
|
|
|
if (!module.parent) { |
|
|
|
this.loadModules(); |
|
|
|
await this.lib('judger').connect(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// redis and redisCache is for syzoj-renderer
|
|
|
|
// redis and redisCache is for syzoj-renderer
|
|
|
|
const redis = require('redis'); |
|
|
|
const redis = require('redis'); |
|
|
@ -91,7 +82,40 @@ global.syzoj = { |
|
|
|
set: util.promisify(this.redis.set).bind(this.redis) |
|
|
|
set: util.promisify(this.redis.set).bind(this.redis) |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
this.loadModules(); |
|
|
|
if (!module.parent) { |
|
|
|
|
|
|
|
// Loaded by node CLI, not by `require()`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (process.send) { |
|
|
|
|
|
|
|
// if it's started by child_process.fork(), it must be requested to restart
|
|
|
|
|
|
|
|
// wait until parent process quited.
|
|
|
|
|
|
|
|
await new Promise((resolve, reject) => { |
|
|
|
|
|
|
|
process.on('message', message => { |
|
|
|
|
|
|
|
if (message === 'quited') resolve(); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
process.send('quit'); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await this.lib('judger').connect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)}...`); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
restart() { |
|
|
|
|
|
|
|
console.log('Will now fork a new process.'); |
|
|
|
|
|
|
|
const child = require('child_process').fork(__filename, ['-c', options.config]); |
|
|
|
|
|
|
|
child.on('message', (message) => { |
|
|
|
|
|
|
|
if (message !== 'quit') return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('Child process requested "quit".') |
|
|
|
|
|
|
|
child.send('quited', err => { |
|
|
|
|
|
|
|
if (err) console.error('Error sending "quited" to child process:', err); |
|
|
|
|
|
|
|
process.exit(); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
}, |
|
|
|
}, |
|
|
|
async connectDatabase() { |
|
|
|
async connectDatabase() { |
|
|
|
let Sequelize = require('sequelize'); |
|
|
|
let Sequelize = require('sequelize'); |
|
|
@ -143,7 +167,7 @@ global.syzoj = { |
|
|
|
global.Promise = Sequelize.Promise; |
|
|
|
global.Promise = Sequelize.Promise; |
|
|
|
this.db.countQuery = async (sql, options) => (await this.db.query(`SELECT COUNT(*) FROM (${sql}) AS \`__tmp_table\``, options))[0][0]['COUNT(*)']; |
|
|
|
this.db.countQuery = async (sql, options) => (await this.db.query(`SELECT COUNT(*) FROM (${sql}) AS \`__tmp_table\``, options))[0][0]['COUNT(*)']; |
|
|
|
|
|
|
|
|
|
|
|
this.loadModels(); |
|
|
|
await this.loadModels(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
loadModules() { |
|
|
|
loadModules() { |
|
|
|
fs.readdir('./modules/', (err, files) => { |
|
|
|
fs.readdir('./modules/', (err, files) => { |
|
|
@ -155,7 +179,7 @@ global.syzoj = { |
|
|
|
.forEach((file) => this.modules.push(require(`./modules/${file}`))); |
|
|
|
.forEach((file) => this.modules.push(require(`./modules/${file}`))); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
}, |
|
|
|
loadModels() { |
|
|
|
async loadModels() { |
|
|
|
fs.readdir('./models/', (err, files) => { |
|
|
|
fs.readdir('./models/', (err, files) => { |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
this.log(err); |
|
|
|
this.log(err); |
|
|
@ -163,9 +187,8 @@ global.syzoj = { |
|
|
|
} |
|
|
|
} |
|
|
|
files.filter((file) => file.endsWith('.js')) |
|
|
|
files.filter((file) => file.endsWith('.js')) |
|
|
|
.forEach((file) => require(`./models/${file}`)); |
|
|
|
.forEach((file) => require(`./models/${file}`)); |
|
|
|
|
|
|
|
|
|
|
|
this.db.sync(); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
await this.db.sync(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
lib(name) { |
|
|
|
lib(name) { |
|
|
|
return require(`./libs/${name}`); |
|
|
|
return require(`./libs/${name}`); |
|
|
|