webapi-eca/js/eventpoller.js

154 lines
No EOL
4.7 KiB
JavaScript

// # Event Poller
'use strict';
var fs = require('fs'),
path = require('path'),
log = require('./logging'),
listMessageActions = {},
listAdminCommands = {},
listEventModules = {},
listPoll = {}, //TODO this will change in the future because it could have
//several parameterized (user-specific) instances of each event module
isRunning = true,
eId = 0,
db, ml;
//TODO allow different polling intervals (a wrapper together with settimeout per to be polled could be an easy and solution)
function init() {
if(process.argv.length > 2) log({ logType: parseInt(process.argv[2]) || 0 });
var args = { logType: log.getLogType() };
ml = require('./module_loader')(args);
db = require('./db_interface')(args);
initAdminCommands();
initMessageActions();
pollLoop();
};
function loadEventModule(el, cb) {
if(db && ml) db.getEventModule(el, function(err, obj) {
if(err || !obj) {
if(typeof cb === 'function') cb(new Error('Retrieving Event Module ' + el + ' from DB: ' + err));
else log.error('EP', 'Retrieving Event Module ' + el + ' from DB!');
}
else {
// log.print('EP', 'Loading Event Module: ' + el);
try {
var m = ml.requireFromString(obj, el);
db.getEventModuleAuth(el, function(mod) {
return function(err, objA) {
//TODO authentication needs to be done differently
if(objA && mod.loadCredentials) mod.loadCredentials(JSON.parse(objA));
};
}(m));
listEventModules[el] = m;
if(typeof cb === 'function') cb(null, m);
} catch(e) {
if(typeof cb === 'function') cb(e);
else log.error(e);
}
}
});
}
function fetchPollFunctionFromModule(mod, func) {
for(var i = 1; i < func.length; i++) {
if(mod) mod = mod[func[i]];
}
if(mod) {
log.print('EP', 'Found active event module "' + func.join('->') + '", adding it to polling list');
//FIXME change this to [module][prop] = module; because like this identical properties get overwritten
// also add some on a per user basis information because this should go into a user context for the users
// that sat up this rule!
listPoll[func.join('->')] = mod;
} else {
log.print('EP', 'No property "' + func.join('->') + '" found');
}
}
function initMessageActions() {
listMessageActions['event'] = function(args) {
var prop = args[1], arrModule = prop.split('->');
if(arrModule.length > 1){
if(listEventModules[arrModule[0]]) {
fetchPollFunctionFromModule(listEventModules[arrModule[0]], arrModule);
} else {
log.print('EP', 'Event Module ' + arrModule[0] + ' needs to be loaded, doing it now...');
loadEventModule(arrModule[0], function(err, obj) {
if(err || !obj) log.error('EP', 'Event Module "' + arrModule[0] + '" not found: ' + err);
else {
log.print('EP', 'Event Module ' + arrModule[0] + ' found and loaded');
fetchPollFunctionFromModule(obj, arrModule);
}
});
}
}
};
//TODO this goes into module_manager, this will receive notification about
// new loaded/stored event modules and fetch them from the db
listMessageActions['cmd'] = function(args) {
var func = listAdminCommands[args[1]];
if(typeof(func) === 'function') func(args);
};
process.on('message', function(strProps) {
var arrProps = strProps.split('|');
if(arrProps.length < 2) log.error('EP', 'too few parameter in message!');
else {
var func = listMessageActions[arrProps[0]];
if(func) func(arrProps);
}
});
}
function initAdminCommands() {
listAdminCommands['shutdown'] = function(args) {
log.print('EP', 'Shutting down DB Link');
isRunning = false;
if(db) db.shutDown();
};
}
function checkRemotes() {
for(var prop in listPoll) {
try {
listPoll[prop](
/*
* define and immediately call anonymous function with param prop.
* This places the value of prop into the context of the callback
* and thus doesn't change when the for loop keeps iterating over listPoll
* TODO add this example to the documentation and elaborate
*/
(function(p) {
return function(err, obj) {
if(err) {
err.additionalInfo = 'module: ' + p;
log.error('EP', err);
} else {
process.send({
event: p,
eventid: 'polled_' + eId++,
payload: obj
});
}
};
})(prop)
);
} catch (e) {
log.error('EP', e);
}
}
}
function pollLoop() {
if(isRunning) {
checkRemotes();
setTimeout(pollLoop, 10000);
}
}
init();