Commit 938af859 authored by priit's avatar priit
Browse files

KEELELIIN-40

parent 0b13eade
......@@ -5,8 +5,9 @@ node_modules
.idea
dump.rdb
scan
tests/contentTokenizer.js
tests/jmeter.log
tests/94megafile
tests/189megafile
keeleliin.log
\ No newline at end of file
tmp_tests/contentTokenizer.js
tmp_tests/jmeter.log
tmp_tests/94megafile
tmp_tests/189megafile
keeleliin.log
coverage
\ No newline at end of file
global.__base = __dirname + '/';
var express = require('express');
var app = express();
var server = require('./www/server');
var log4js = require('log4js');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');
var multer = require('multer');
var debug = require('debug')('keeleliin-wrapper:server');
var cluster = require('cluster');
var http = require('http');
var config = require('./config');
var controllers = require('./controllers');
var routerMiddleware = require('./middlewares/router');
var errorhandlerMiddleware = require('./middlewares/errorhandler');
app.set('views', path.join(__dirname, 'views'));// view engine setup
app.set('view engine', 'jade');// view engine setup
log4js.configure({
appenders: [
{ type: 'console',
layout: {
type: 'pattern',
pattern: "[%d] [%[%x{pid}] [%5.5p%]] - %m",
tokens: {
pid: process.pid
}
}
},
{ type: 'file', filename: 'keeleliin.log' }
]
});
var log4jsLogger = log4js.getLogger('app_js');
app.use(logger('dev'));
app.use(bodyParser.json({limit: '1000mb'})); // for parsing application/json
app.use(multer({ dest: './uploads/'})); // for parsing multipart/form-data
app.use(express.static(path.join(__dirname, 'public')));
app.use(routerMiddleware.routeLogger);
app.use(errorhandlerMiddleware.common);
app.use(controllers);
app.use(errorhandlerMiddleware.error404);
/**
* Create HTTP server.
*/
var numCPUs = require('os').cpus().length;
numCPUs = 1; //todo delete
///
if (cluster.isMaster) {
log4jsLogger.debug('NumCPUs: ' + numCPUs);
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
log4jsLogger.info('worker ' + worker.process.pid + ' died; Code: ' + code + '; Signal: ' + signal);
});
} else {
var port = normalizePort(config.port);
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
}
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
log4jsLogger.debug('Listening on ' + bind + ' process: ' + process.pid );
}
module.exports = app;
\ No newline at end of file
server.startCluster(1, function ( err ) {
console.log('Server started ' + process.pid);
});
\ No newline at end of file
......@@ -32,8 +32,7 @@ config.service = {
serviceRequestTemplate: {
service: {
meta: { //key: value
isAsync: null, // vaikimisi on teenus asünkroone,
sessionId: null // vaikimisi seda ei määrata
isAsync: null // vaikimisi on teenus asünkroone,
},
params: {
//data: null,
......
......@@ -24,7 +24,10 @@ router.get('/:instanceId', function(req, res) {
var wrapperService = new WrapperService();
wrapperService.getServiceResponse(req.params.instanceId, function (err, data) {
if(err) return res.send({errors: err});
if(err){
return res.status(404).send({errors: err});
}
res.send(data);
});
});
......
/**
* Created by priit on 27.05.15.
*/
var debug = require('debug')('errorhandler');
var logger = require('log4js').getLogger('router_middleware');
var express = require('express');
var app = express();
module.exports = {
common: function(err, req, res, next) {
debug('Error happened');
debug(err.stack);
if (app.get('env') === 'development') {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
}
logger.error(err.stack);
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
res.send({
errors: err.message
});
},
error404: function(req, res, next) {
debug('Error 404 happened');
var err = new Error('Not Found');
err.status = 404;
next(err);
logger.error('Error 404 happened');
res.status(404);
res.send({
errors: 'Lehekülge ei leitud'
});
}
};
\ No newline at end of file
......@@ -3,7 +3,8 @@
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./app.js"
"start": "node ./app.js",
"test": "./node_modules/.bin/istanbul test _mocha -- -R spec --timeout 15000"
},
"dependencies": {
"body-parser": "~1.12.4",
......@@ -17,5 +18,11 @@
"randomstring": "^1.0.5",
"redis": "^0.12.1",
"request": "^2.57.0"
},
"devDependencies": {
"assert": "^1.3.0",
"istanbul": "^0.3.15",
"should": "^7.0.1",
"supertest": "^1.0.1"
}
}
var logger = require('log4js').getLogger('service_request');
var config = require('../../config');
var sessionService = require('../service/sessionService');
function ServiceRequest( requestData ) {
var self = this;
......@@ -33,10 +32,6 @@ function ServiceRequest( requestData ) {
} else {
self.data.service.meta.isAsync = staticOptions.isAsync;
}
if(!self.data.service.meta.sessionId){
self.data.service.meta.sessionId = sessionService.generateId();
}
};
this._mapParams = function(){
......
......@@ -6,13 +6,11 @@ var config = require(__base + 'config');
var DaoService = function(){
var self = this;
var connected = false;
this.client = redis.createClient(config.redis.port, config.redis.host, {});
this.client.on('connect', function() {
logger.info('connected');
self.connected = true;
});
this.client.on("error", function (err) {
......@@ -41,7 +39,7 @@ var DaoService = function(){
return cb(err);
}
logger.debug('Got redis data');
logger.debug(reply);
if(cb != undefined){
return cb(null, reply);
}
......
......@@ -4,6 +4,7 @@ var config = require('../../config');
var fs = require('fs');
var daoService = require('./daoService');
var Session = require('../model/session');
var FileUtil = require('../util/file');
function SessionService() {
......@@ -17,14 +18,18 @@ function SessionService() {
daoService.get(sessionId, function (err, session) {
if(err) return callback(err);
if (session == null) {
session = new Session(sessionId);
if(session == null){
return callback({session: 'Sessiooni ei leitud'});
}
callback(null, session);
});
};
this.createSession = function () {
var sessionId = self.generateId();
return new Session(sessionId);
};
this.getStorePath = function (sessionId) {
return config.service.staticOptions.storagePath + '/' + sessionId;
};
......@@ -85,7 +90,7 @@ function SessionService() {
this.removeSession = function (sessionId, callback) {
self._removeStorage(self.getStorePath(sessionId), function () {
FileUtil.rmdir(self.getStorePath(sessionId), function () {
logger.debug('Session file storage removed');
daoService.delete(sessionId, function (err) {
logger.debug('Session redis storage removed');
......@@ -94,52 +99,6 @@ function SessionService() {
})
};
this._removeStorage = function (path, callback) {
var rmdirAsync = function (path, callback) {
fs.readdir(path, function (err, files) {
if (err) {
// Pass the error on to callback
callback(err, []);
return;
}
var wait = files.length,
count = 0,
folderDone = function (err) {
count++;
// If we cleaned out all the files, continue
if (count >= wait || err) {
fs.rmdir(path, callback);
}
};
// Empty directory to bail early
if (!wait) {
folderDone();
return;
}
// Remove one or more trailing slash to keep from doubling up
path = path.replace(/\/+$/, "");
files.forEach(function (file) {
var curPath = path + "/" + file;
fs.lstat(curPath, function (err, stats) {
if (err) {
callback(err, []);
return;
}
if (stats.isDirectory()) {
rmdirAsync(curPath, folderDone);
} else {
fs.unlink(curPath, folderDone);
}
});
});
});
};
rmdirAsync(path, callback);
};
this.saveSession = function (session, callback) {
daoService.set(session.id, session, function (err) {
callback(err, session);
......
......@@ -22,15 +22,12 @@ function WrapperService() {
if(err) return callback(err);
sessionService.closeSession(session, finalPipecontent, function (err, session) {
logger.debug('Sessioon on lõpetanud ja savestatud');
if (session.isAsync == false) {
logger.debug('Send response');
if(err) return callback(err);
self.getServiceResponse(session.id, callback);
}
});
});
});
......@@ -38,23 +35,23 @@ function WrapperService() {
this._initSession = function(serviceRequest, callback){
sessionService.getSession( serviceRequest.service.meta.sessionId, function(err, session){
var session = sessionService.createSession();
session.message = Session.messages.RUNNING;
session.success = true;
session.isAsync = serviceRequest.service.meta.isAsync;
session.isFinished = false;
sessionService.saveSession(session, function(err){
if(err) return callback(err);
session.message = Session.messages.RUNNING;
session.success = true;
session.isAsync = serviceRequest.service.meta.isAsync;
session.isFinished = false;
sessionService.saveSession(session, function(err){
if(err) return callback(err);
return callback(null, session);
});
return callback(null, session);
});
};
this.getServiceResponse = function (instanceId, callback) {
sessionService.getSession(instanceId, function (err, session) {
if(err) return callback(err);
if(err){
return callback(err);
}
//logger.debug(session);
sessionService.getApiResponse(session, callback);
});
};
......
/**
* Created by priit on 17.06.15.
*/
var fs = require('fs');
var FileUtil = {
mv: function(source, target, callback) {
FileUtil.cp(source, target, function (err) {
if(err) return callback(err);
fs.unlink(source, callback);
});
},
cp: function(source, target, callback) {
var cbCalled = false;
var rd = fs.createReadStream(source);
rd.on("error", function(err) {
done(err);
});
var wr = fs.createWriteStream(target);
wr.on("error", function(err) {
done(err);
});
wr.on("close", function(ex) {
done();
});
rd.pipe(wr);
function done(err) {
if (!cbCalled) {
callback(err);
cbCalled = true;
}
}
},
rmdir: function(path, callback){
var rmdirAsync = function (path, callback) {
fs.readdir(path, function (err, files) {
if (err) {
// Pass the error on to callback
callback(err, []);
return;
}
var wait = files.length,
count = 0,
folderDone = function (err) {
count++;
// If we cleaned out all the files, continue
if (count >= wait || err) {
fs.rmdir(path, callback);
}
};
// Empty directory to bail early
if (!wait) {
folderDone();
return;
}
// Remove one or more trailing slash to keep from doubling up
path = path.replace(/\/+$/, "");
files.forEach(function (file) {
var curPath = path + "/" + file;
fs.lstat(curPath, function (err, stats) {
if (err) {
callback(err, []);
return;
}
if (stats.isDirectory()) {
rmdirAsync(curPath, folderDone);
} else {
fs.unlink(curPath, folderDone);
}
});
});
});
};
rmdirAsync(path, callback);
}
};
module.exports = FileUtil;
\ No newline at end of file
/**
* Created by priit on 18.06.15.
*/
var Server = {
normalizePort: function(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
},
onError: function(error) {
if (error.syscall !== 'listen') {
throw error;
}
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error('Port requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error('Port is already in use');
process.exit(1);
break;
default:
throw error;
}
}
};
module.exports = Server;
/**
* Created by priit on 18.06.15.
*/
var integrationTest = require('./integration');
var unit = require('./unit');
\ No newline at end of file
/**
* Created by priit on 18.06.15.
*/
var routesTests = require('./routes');
\ No newline at end of file
/**
* sudo npm install -g mocha
*/
var server = require('../../www/server');
var config = require('../../config');
var should = require('should');
var assert = require('assert');
var request = require('supertest');
describe('Routing', function() {
var url = 'http://127.0.0.1:' + config.port;
before(function(done) {
server.startInstance( function(){
done();
});
});
describe('Service', function() {
it('Tagastab api kirjelduse lehe', function(done) {
request(url)
.get('/')
.expect(200)
.expect('Content-Type', /html/)
.end(function(err, res) {
if (err) {
throw err;
}
done();
});
});
it('Mitteeksisteeriv url tagastab json veateate', function(done) {
request(url)
.get('/midagisuvalist')
.expect(404)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) {
throw err;
}