Keep containers running instead of making new ones
This commit is contained in:
parent
b45e7c69e3
commit
389b00ba15
3 changed files with 77 additions and 23 deletions
18
src/commands/exit.js
Normal file
18
src/commands/exit.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const { Command } = require('discord-akairo');
|
||||||
|
|
||||||
|
class ExitCommand extends Command {
|
||||||
|
constructor() {
|
||||||
|
super('exit', {
|
||||||
|
aliases: ['exit'],
|
||||||
|
ownerOnly: true,
|
||||||
|
clientPermissions: ['SEND_MESSAGES']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async exec() {
|
||||||
|
await this.client.languageHandler.cleanup();
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ExitCommand;
|
|
@ -27,7 +27,7 @@ class MessageInvalidListener extends Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
let errored = false;
|
let errored = false;
|
||||||
const result = await this.client.languageHandler.evalCode(message, parse)
|
const result = await this.client.languageHandler.evalCode(parse)
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
errored = true;
|
errored = true;
|
||||||
return e.message;
|
return e.message;
|
||||||
|
|
|
@ -23,6 +23,7 @@ class LanguageHandler extends AkairoHandler {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.aliases = new Collection();
|
this.aliases = new Collection();
|
||||||
|
this.containers = new Collection();
|
||||||
}
|
}
|
||||||
|
|
||||||
register(language, filepath) {
|
register(language, filepath) {
|
||||||
|
@ -59,30 +60,50 @@ class LanguageHandler extends AkairoHandler {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
evalCode(message, { language, code, options }) {
|
async setupContainer(id) {
|
||||||
return new Promise((resolve, reject) => {
|
if (this.containers.has(id)) {
|
||||||
const name = `comp_iler-${message.id}-${Date.now()}`;
|
return this.containers.get(id);
|
||||||
const { id = language.id, env = {} } = language.runWith(options);
|
}
|
||||||
|
|
||||||
|
const name = `comp_iler-${id}-${Date.now()}`;
|
||||||
const proc = childProcess.spawn('docker', [
|
const proc = childProcess.spawn('docker', [
|
||||||
'run', '--rm', `--name=${name}`, '-u1000', '-w/tmp/',
|
'run', '--rm', `--name=${name}`, '-u1000', '-w/tmp/', '-t', '-d',
|
||||||
'--net=none', `--cpus=${this.client.config.cpus}`, `-m=${this.client.config.memory}`,
|
'--net=none', `--cpus=${this.client.config.cpus}`, `-m=${this.client.config.memory}`,
|
||||||
...Object.entries(env).map(([k, v]) => `-e${k}=${v}`),
|
`1computer1/comp_iler:${id}`
|
||||||
`1computer1/comp_iler:${id}`,
|
|
||||||
'/bin/sh', '/var/run/run.sh', code
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
try {
|
||||||
if (process.platform === 'win32') {
|
await this.handleSpawn(proc);
|
||||||
childProcess.execSync(`docker kill --signal=9 ${name} >nul 2>nul`);
|
this.containers.set(id, { name });
|
||||||
} else {
|
return this.containers.get(id);
|
||||||
childProcess.execSync(`docker kill --signal=9 ${name} >/dev/null 2>/dev/null`);
|
} catch (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reject(new Error('Timed out'));
|
async evalCode({ language, code, options }) {
|
||||||
} catch (e) {
|
const { id = language.id, env = {} } = language.runWith(options);
|
||||||
reject(e);
|
const { name } = await this.setupContainer(id);
|
||||||
|
const proc = childProcess.spawn('docker', [
|
||||||
|
'exec',
|
||||||
|
...Object.entries(env).map(([k, v]) => `-e${k}=${v}`),
|
||||||
|
name, '/bin/sh', '/var/run/run.sh', code
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await this.handleSpawn(proc);
|
||||||
|
return result;
|
||||||
|
} catch (err) {
|
||||||
|
this.images.delete(id);
|
||||||
|
await this.kill(name);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSpawn(proc) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('Timed out'));
|
||||||
}, this.client.config.timeout);
|
}, this.client.config.timeout);
|
||||||
|
|
||||||
let data = '';
|
let data = '';
|
||||||
|
@ -108,6 +129,21 @@ class LanguageHandler extends AkairoHandler {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kill(name) {
|
||||||
|
let cmd;
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
cmd = `docker kill --signal=9 ${name} >nul 2>nul`;
|
||||||
|
} else {
|
||||||
|
cmd = `docker kill --signal=9 ${name} >/dev/null 2>/dev/null`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.promisify(childProcess.exec)(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
return Promise.all(this.images.map(({ name }) => this.kill(name)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = LanguageHandler;
|
module.exports = LanguageHandler;
|
||||||
|
|
Loading…
Reference in a new issue