Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Compiled source #
###################
*.com
Expand Down
209 changes: 101 additions & 108 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,126 +1,119 @@
const tar = require('tar-stream');
const fs = require('fs');
const commandLineArgs = require('command-line-args');


/**
* Command line arguments definition
* @type {[*]}
*/
const commandLineDef = [
{ name: 'port', alias: 'p', type: Number, defaultValue: 5016},
{ name: 'mongoAddress', alias: 'a', type: String, defaultValue: '127.0.0.1/queue'},
{ name: 'mongoCollection', alias: 'c', type: String, defaultValue: 'agendaJobs'},
{ name: 'defaultConcurrency', alias: 'd', type: Number, defaultValue: 40},
{ name: 'maxConcurrency', alias: 'm', type: Number, defaultValue: 70}
];
/**
* Object that for keys has command line argument names
* and for values its value.
* @type {Object}
*/
const commandLine = commandLineArgs(commandLineDef);


/**
* Server specified in server.js
* @type {Server}
*/
const server = require('./server')(
commandLine.port,
commandLine.mongoAddress,
commandLine.mongoCollection,
commandLine.defaultConcurrency,
commandLine.maxConcurrency);
/**
* Object controlling docker specified in javaBox.js
* @type {EventEmitter}
*/
const javaBox = require('./javaBox');

/**
* Specifying the server and javaBox control flow
*/
server.on('runJunit', runJunit);
server.on('runJava', runJava);
javaBox.on('result', giveFeedBack);


/**
* Given code to execute and info about it,
* creates a tar with the code and passed the info and the tar to javaBox.
*
* @param messageId {String}: id of the given message/request.
* @param main {String}: entry point class name.
* @param files [{name: {String}, data: {String]: array of objects with filename and its content
* @param timeLimitCompileMs {Number}: Compilation timeout.
* @param timeLimitExecutionMs {Number}: Execution timeout.
*/
function runJava(messageId, main, files, timeLimitCompileMs, timeLimitExecutionMs) {

let filesToAdd = files.length;

const pack = tar.pack();

const tryTarAndRun = () => {

filesToAdd--;

if (filesToAdd === 0) {
const Promise = require('bluebird');
const coroutine = Promise.coroutine;


const main = coroutine(function*() {
/**
* Command line arguments definition
* @type {[*]}
*/
const commandLineDef = [
{name: 'port', alias: 'p', type: Number, defaultValue: 5016},
{name: 'mongoAddress', alias: 'a', type: String, defaultValue: '127.0.0.1/queue'},
{name: 'mongoCollection', alias: 'c', type: String, defaultValue: 'agendaJobs'},
{name: 'defaultConcurrency', alias: 'd', type: Number, defaultValue: 40},
{name: 'maxConcurrency', alias: 'm', type: Number, defaultValue: 70}
];
/**
* Object that for keys has command line argument names
* and for values its value.
* @type {Object}
*/
const commandLine = commandLineArgs(commandLineDef);


/**
* Server specified in server.js
* @type {Server}
*/
const server = yield require('./server')(
commandLine.port,
commandLine.mongoAddress,
commandLine.mongoCollection,
commandLine.defaultConcurrency,
commandLine.maxConcurrency
);

/**
* Object controlling docker specified in javaBox.js
* @type {EventEmitter}
*/
const javaBox = require('./javaBox');

/**
* Given code to execute and info about it,
* creates a tar with the code and passed the info and the tar to javaBox.
*
* @param messageId {String}: id of the given message/request.
* @param main {String}: entry point class name.
* @param files {{name: String, data: String}[]}: array of objects with filename and its content
* @param timeLimitCompileMs {Number}: Compilation timeout.
* @param timeLimitExecutionMs {Number}: Execution timeout.
*/
const runJava = coroutine(function*(messageId, main, files, timeLimitCompileMs, timeLimitExecutionMs) {

const pack = tar.pack();
//const packEntry = Promise.promisify(pack.entry, {context: pack});

Promise.map(files, function (file) {
//return packEntry({name: file.name}, file.data);
return pack.entry({name: file.name}, file.data);

}).then(function () {
const tarBuffer = pack.read();
javaBox.emit('runJava', messageId, main, tarBuffer, timeLimitCompileMs, timeLimitExecutionMs);
}
};

files.forEach((file) => {
pack.entry({ name: file.name }, file.data, tryTarAndRun);
});
}

/**
* Given code to execute and to test and info about it,
* creates a tar with the code and passed the info and the tar to javaBox.
*
* @param messageId {String}: id of the given message/request.
* @param tests [{name: {String}, data: {String]: array of objects with filename and its content.
* @param files [{name: {String}, data: {String]: array of objects with filename and its content.
* @param timeLimitCompileMs {Number}: Compilation timeout.
* @param timeLimitExecutionMs {Number}: Execution timeout.
*/
function runJunit(messageId, tests, files, timeLimitCompileMs, timeLimitExecutionMs) {

let filesToAdd = files.length + tests.length;
});

const pack = tar.pack();

const tryTarAndRun = () => {

filesToAdd--;

if (filesToAdd === 0) {
});
/**
* Given code to execute and to test and info about it,
* creates a tar with the code and passed the info and the tar to javaBox.
*
* @param messageId {String}: id of the given message/request.
* @param tests [{name: {String}, data: {String]: array of objects with filename and its content.
* @param files [{name: {String}, data: {String]: array of objects with filename and its content.
* @param timeLimitCompileMs {Number}: Compilation timeout.
* @param timeLimitExecutionMs {Number}: Execution timeout.
*/
const runJunit = coroutine(function *(messageId, tests, files, timeLimitCompileMs, timeLimitExecutionMs) {

files = files.concat(tests);

const pack = tar.pack();
const packEntry = Promise.promisify(pack.entry, {context: pack});

Promise.map(files, function (file) {
return packEntry({name: file.name}, file.data);

}).then(function () {
const tarBuffer = pack.read();
javaBox.emit('runJunit', messageId, tests, tarBuffer, timeLimitCompileMs, timeLimitExecutionMs);
}
};

files.forEach((file) => {
pack.entry({ name: file.name }, file.data, tryTarAndRun);
});
});

tests.forEach((test) => {
pack.entry({ name: test.name }, test.data, tryTarAndRun);
});
}

/**
* Given the feedback object passes it to the server.
* @param feedback {Object}, feedback/result object as specified in readme or javaBox.js
*/
function giveFeedBack(feedback) {
/**
* Given the feedback object passes it to the server.
* @param feedback {Object}, feedback/result object as specified in readme or javaBox.js
*/
function giveFeedBack(feedback) {

server.emit('result', feedback);
}
server.emit('result', feedback);
}

/**
* Specifying the server and javaBox control flow
*/

server.on('runJunit', runJunit);
server.on('runJava', runJava);
javaBox.on('result', giveFeedBack);

});

main();
30 changes: 30 additions & 0 deletions containerOutputStream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Module for creating custom writable streams in order to get the stdout and stderr from the containers
*/

const stream = require('stream');
const util = require('util');
const Writable = stream.Writable;


function OutputStream(options) {
if (!(this instanceof OutputStream)) return new OutputStream(options);

Writable.call(this, options);
this.memStore = new Buffer('');

this.toString = function () {
return this.memStore.toString()
}
}

util.inherits(OutputStream, Writable);

OutputStream.prototype._write = function (chunk, enc, cb) {

const buffer = (Buffer.isBuffer(chunk)) ? chunk : new Buffer(chunk, enc);
this.memStore = Buffer.concat([this.memStore, buffer]);
cb();
};

module.exports = OutputStream;
Loading