restructured the http listener

This commit is contained in:
Dominic Bosch 2014-02-19 17:04:49 +01:00
parent 20748240c2
commit e31da1e5a0
11 changed files with 175 additions and 74 deletions

View file

@ -80,16 +80,16 @@ initRouting = ( port ) =>
# - **`POST` to _"/user"_:** User requests are possible for all users with an account
app.post '/usercommand', requestHandler.handleUserCommand
try
@server = app.listen parseInt( port ) || 8125 # inbound event channel
server = app.listen parseInt( port ) || 8125 # inbound event channel
###
Error handling of the express port listener requires special attention,
thus we have to catch the error, which is issued if the port is already in use.
###
@server.on 'listening', () =>
addr = @server.address()
server.on 'listening', () =>
addr = server.address()
if addr.port is not port
@shutDownSystem()
@server.on 'error', ( err ) =>
server.on 'error', ( err ) =>
if err.errno is 'EADDRINUSE'
@log.error err, 'HL | http-port already in use, shutting down!'
@shutDownSystem()
@ -105,13 +105,16 @@ exports.addShutdownHandler = ( fShutDown ) =>
@shutDownSystem = fShutDown
requestHandler.addShutdownHandler fShutDown
###
Shuts down the http listener.
@public shutDown()
###
exports.shutDown = () =>
@log.warn 'HL | Shutting down HTTP listener'
try
@server.close()
# There's no way to gracefully stop express from running, thus the main
# module needs to call process.exit() at the very end of its existance... thanks
# ###
# Shuts down the http listener.
# @public shutDown()
# ###
# exports.shutDown = () =>
# @log?.warn 'HL | Shutting down HTTP listener'
# # Yeah I know the discussion... let's assume the system runs forever
# process.exit()

View file

@ -41,8 +41,12 @@ exports = module.exports = ( args ) =>
@crypto_key = "}f6y1y}B{.an$}2c$Yl.$mSnF\\HX149u*y8C:@kmN/520Gt\\v'+KFBnQ!\\r<>5X/xRI`sT<Iw;:DPV;4gy:qf]Zq{\"6sgK{,}^\"!]O;qBM3G?]h_`Psw=b6bVXKXry7*"
@db = redis.createClient args[ 'db-port' ],
'localhost', { connect_timeout: 2000 }
# Eventually we try to connect to the wrong port, redis will emit an error that we
# need to catch and take into account when answering the isConnected function call
@db.on 'error', ( err ) =>
@log.warn err, 'message from DB'
if err.message.indexOf 'ECONNREFUSED' > -1
@connRefused = true
@log.error err, 'DB | Wrong port?'
@ep = new IndexedModules( 'event-poller', @db, @log )
@ai = new IndexedModules( 'action-invoker', @db, @log )
@ -54,17 +58,21 @@ ten attempts within five seconds, or nothing on success to the callback(err).
@param {function} cb
###
exports.isConnected = ( cb ) =>
if @db.connected then cb()
if @db.connected
cb()
else
numAttempts = 0
fCheckConnection = =>
if @db.connected
@log.info 'DB | Successfully connected to DB!'
cb()
else if numAttempts++ < 10
setTimeout fCheckConnection, 100
if @connRefused
cb new Error 'DB | Connection refused! Wrong port?'
else
cb new Error 'Connection to DB failed!'
if @db.connected
@log.info 'DB | Successfully connected to DB!'
cb()
else if numAttempts++ < 10
setTimeout fCheckConnection, 100
else
cb new Error 'DB | Connection to DB failed!'
setTimeout fCheckConnection, 100
###

View file

@ -120,13 +120,14 @@ init = =>
logconf: logconf
# > Fetch the `http-port` argument
args[ 'http-port' ] = parseInt argv.w || conf.getHttpPort()
args[ 'db-port' ] = parseInt argv.w || conf.getDbPort()
args[ 'db-port' ] = parseInt argv.d || conf.getDbPort()
@log.info 'RS | Initialzing DB'
db args
# > We only proceed with the initialization if the DB is ready
db.isConnected ( err, result ) =>
db.isConnected ( err ) =>
if err
@log.error 'RS | No DB connection, shutting down system!'
shutDown()
else
@ -163,7 +164,7 @@ Shuts down the server.
shutDown = =>
@log.warn 'RS | Received shut down command!'
engine?.shutDown()
http?.shutDown()
# We need to force stop express (in http-listener module)
process.exit()
###

View file

@ -227,7 +227,7 @@ function preprocessActionArguments(evt, act, res) {
}
exports.shutDown = function() {
log.info('EN', 'Shutting down Poller and DB Link');
if(log) log.info('EN', 'Shutting down Poller and DB Link');
isRunning = false;
if(poller) poller.send('cmd|shutdown');
if(db) db.shutDown();

View file

@ -48,7 +48,7 @@ HTTP Listener
initRouting = function(port) {
var sess_sec;
var server, sess_sec;
app.use(express.cookieParser());
sess_sec = "149u*y8C:@kmN/520Gt\\v'+KFBnQ!\\r<>5X/xRI`sT<Iw";
app.use(express.session({
@ -65,20 +65,20 @@ HTTP Listener
app.post('/logout', requestHandler.handleLogout);
app.post('/usercommand', requestHandler.handleUserCommand);
try {
_this.server = app.listen(parseInt(port) || 8125);
server = app.listen(parseInt(port) || 8125);
/*
Error handling of the express port listener requires special attention,
thus we have to catch the error, which is issued if the port is already in use.
*/
_this.server.on('listening', function() {
server.on('listening', function() {
var addr;
addr = _this.server.address();
addr = server.address();
if (addr.port === !port) {
return _this.shutDownSystem();
}
});
return _this.server.on('error', function(err) {
return server.on('error', function(err) {
if (err.errno === 'EADDRINUSE') {
_this.log.error(err, 'HL | http-port already in use, shutting down!');
return _this.shutDownSystem();
@ -100,18 +100,4 @@ HTTP Listener
return requestHandler.addShutdownHandler(fShutDown);
};
/*
Shuts down the http listener.
@public shutDown()
*/
exports.shutDown = function() {
_this.log.warn('HL | Shutting down HTTP listener');
try {
return _this.server.close();
} catch (_error) {}
};
}).call(this);

View file

@ -49,7 +49,10 @@ Persistence
connect_timeout: 2000
});
_this.db.on('error', function(err) {
return _this.log.warn(err, 'message from DB');
if (err.message.indexOf('ECONNREFUSED' > -1)) {
_this.connRefused = true;
return _this.log.error(err, 'DB | Wrong port?');
}
});
_this.ep = new IndexedModules('event-poller', _this.db, _this.log);
return _this.ai = new IndexedModules('action-invoker', _this.db, _this.log);
@ -71,13 +74,17 @@ Persistence
} else {
numAttempts = 0;
fCheckConnection = function() {
if (_this.db.connected) {
_this.log.info('DB | Successfully connected to DB!');
return cb();
} else if (numAttempts++ < 10) {
return setTimeout(fCheckConnection, 100);
if (_this.connRefused) {
return cb(new Error('DB | Connection refused! Wrong port?'));
} else {
return cb(new Error('Connection to DB failed!'));
if (_this.db.connected) {
_this.log.info('DB | Successfully connected to DB!');
return cb();
} else if (numAttempts++ < 10) {
return setTimeout(fCheckConnection, 100);
} else {
return cb(new Error('DB | Connection to DB failed!'));
}
}
};
return setTimeout(fCheckConnection, 100);

View file

@ -129,12 +129,13 @@ WebAPI-ECA Engine
logconf: logconf
};
args['http-port'] = parseInt(argv.w || conf.getHttpPort());
args['db-port'] = parseInt(argv.w || conf.getDbPort());
args['db-port'] = parseInt(argv.d || conf.getDbPort());
_this.log.info('RS | Initialzing DB');
db(args);
return db.isConnected(function(err, result) {
return db.isConnected(function(err) {
var cliArgs, poller;
if (err) {
_this.log.error('RS | No DB connection, shutting down system!');
return shutDown();
} else {
_this.log.info('RS | Initialzing engine');
@ -164,9 +165,6 @@ WebAPI-ECA Engine
if (engine != null) {
engine.shutDown();
}
if (http != null) {
http.shutDown();
}
return process.exit();
};

View file

@ -0,0 +1,79 @@
path = require 'path'
needle = require 'needle'
logger = require path.join '..', 'js-coffee', 'logging'
log = logger.getLogger
nolog: true
exports.testShutDown = ( test ) =>
test.expect 1
http = require path.join '..', 'js-coffee', 'http-listener'
http.addShutdownHandler () ->
console.log 'shutdown handler called!'
http.shutDown()
test.done()
process.exit()
args = {
logger: log
}
args[ 'http-port' ] = 8080
http args
test.ok true, 'yay'
fWait = () ->
needle.get 'localhost:8080/forge_modules', (err, resp, body) ->
console.log 'http'
# console.log http
# console.log test
# console.log err
# console.log resp
# console.log body
test.done()
if err
console.log 'got an error on request'
console.log err
else
console.log 'no err'
if resp and resp.statusCode is 200
console.log 'yay got valid answer'
else console.log 'got an'
try
console.log 'trying to shutdown'
console.log http
http.shutDown()
catch e
console.log e
setTimeout fWait, 1000
exports.testWrongPort = ( test ) =>
test.expect 1
test.ok true, 'yay'
test.done()
# http = require path.join '..', 'js-coffee', 'http-listener'
# http.addShutDownHandler () ->
# test.done()
# engine = cp.fork pth, [ '-n' ] # [ '-i' , 'warn' ]
# engine.on 'exit', ( code, signal ) ->
# test.ok true, 'Engine stopped'
# isRunning = false
# test.done()
# fWaitForStartup = () ->
# engine.send 'die'
# setTimeout fWaitForDeath, 5000
# # Garbage collect eventually still running process
# fWaitForDeath = () ->
# if isRunning
# test.ok false, '"testShutDown" Engine didn\'t shut down!'
# engine.kill()
# test.done()
# setTimeout fWaitForStartup, 1000

View file

@ -16,9 +16,9 @@ exports.tearDown = ( cb ) =>
cb()
###
# Test AVAILABILITY
###
# ###
# # Test AVAILABILITY
# ###
exports.Availability =
testRequire: ( test ) =>
test.expect 1
@ -39,7 +39,7 @@ exports.Availability =
opts =
logger: @log
opts[ 'db-port' ] = 63214
opts[ 'db-port' ] = 13410
@db opts
@db.isConnected ( err ) ->
test.ok err, 'Still connected!?'

View file

@ -9,9 +9,8 @@ path = require 'path'
# @engine.send('die')
# cb()
# # TODO wrong db-port or http-port will make the engine stop properly before starting
# # goes hand in hand with wrong config file
# # http command shutdown does it properly, as well as sending the process the die command
# TODO test http shutdown command
# TODO test wrong/invalid config file
exports.testShutDown = ( test ) =>
test.expect 1
@ -100,5 +99,24 @@ exports.testHttpPortInvalid = ( test ) =>
test.ok false, '"testHttpPortInvalid" Engine didn\'t shut down!'
test.done()
setTimeout fWaitForDeath, 1000
exports.testDbPortInvalid = ( test ) =>
test.expect 1
isRunning = true
pth = path.resolve 'js-coffee', 'webapi-eca'
engine = cp.fork pth, ['-n', '-d', '10'] # [ '-i' , 'warn' ]
engine.on 'exit', ( code, signal ) ->
test.ok true, 'Engine stopped'
isRunning = false
test.done()
# Garbage collect eventually still running process
fWaitForDeath = () =>
engine.kill()
if isRunning
test.ok false, '"testHttpPortInvalid" Engine didn\'t shut down!'
test.done()
setTimeout fWaitForDeath, 1000

View file

@ -1,15 +1,16 @@
#!/usr/bin/env node
process.chdir(__dirname);
var fs = require('fs');
var path = require('path');
var args = process.argv.slice(2);
if( args[0] !== undefined ) {
var fl = path.join('testing', args[0]);
if (fs.existsSync(fl)) {
require('nodeunit').reporters.default.run([fl]);
} else {
console.error('File not found!!');
}
process.chdir( __dirname );
var fs = require( 'fs' );
var path = require( 'path' );
var nodeunit = require( 'nodeunit' );
var args = process.argv.slice( 2 );
if( args[ 0 ] !== undefined ) {
var fl = path.resolve( args[ 0 ] );
if ( fs.existsSync( fl ) ) {
nodeunit.reporters.default.run( [ fl ] );
} else {
console.error( 'File not found!!' );
}
} else {
require('nodeunit').reporters.default.run(['testing']);
nodeunit.reporters.default.run( [ 'testing' ] );
}