UNPKG

mhl-dispatcher

Version:

A node dispatcher server for running and managing batch processes

374 lines (352 loc) 12.1 kB
var os = require('os'), db = require('./db.js'), proc = require('./proc.js'), error = require('./error.js'), logger = require('./logger.js'), clc = require('cli-color'), util = require('util'), server = {}; 'use strict'; logger.server = server; //-------------------------------Server Utils---------------------------------------- server.utils = { factory: function(fnName, callback, args){ return function(){ var args = Array.prototype.slice.call(arguments); server.current.funcName = fnName; server.current.funcState = 'started'; if(!logger.silent){ logger.serverLog(server.current.funcName + ' is running.', server.CONSTANTS.Types.INFO); } callback.apply(this, args); }; } }; //--------------Server Settings ------------------------------------------------------ server.hostname = os.hostname(); server.serverId = 0; server.sleep = 1000; server.current = { funcName: '', funcState: '', timeout: null, batch: 0, childProcess: null, childProcessCommand: null }; server.CONSTANTS = { Severity: { SUMMARY: 8, DEBUG: 7, INFO: 6, NOTICE: 5, WARNING: 4, ERROR: 3, CRITICAL: 2, ALERT: 1, EMERGENCY: 0 }, Types: { SUMMARY: 'summary', DEBUG: 'debug', INFO: 'info', NOTICE: 'notice', WARNING: 'warning', ERROR: 'error', CRITICAL: 'critical', ALERT: 'alert', EMERGENCY: 'emergency' } }; //-----------------Server Constants---------------------------------------------------- server.batch = { STATUS: { INPROCESS: 'inprocess', DONE: 'done', ERROR: 'error', KILLED: 'killed' } }; //-------------------Server Status Definitions------------------------------------------- server.status = { starting: { name:'starting', task: server.utils.factory('server.status.starting.task', function(){ server.current.funcState = 'server going into waiting state...'; server.runTask(server.status.waiting); }) }, preparing: { name: 'preparing', task: server.utils.factory('server.status.preparing.task', function(){ server.prepareProcess(function(processReady){ if(processReady){ server.runTask(server.status.processing); }else{ server.runTask(server.status.waiting); } }); }) }, waiting: { name: 'waiting', task: server.utils.factory('server.status.waiting.task', function(){ server.getBatch(function(batchReady){ if(batchReady){ server.runTask(server.status.preparing); }else{ server.runTask (server.status.waiting, server.sleep); } }); }) }, processing: { name: 'processing', task: server.utils.factory('server.status.processing.task', function(){ server.runProcess(function(success){ server.runTask(server.status.waiting); }); logger.silent = true; server.runTask(server.status.processing, server.sleep); }) }, stopping: { name:'stopping', task: server.utils.factory('server.status.stopping.task', function(){ server.killProcess(function(killed){ if(killed){ server.runTask(server.status.waiting, server.sleep); }else{ server.runTask(server.status.stopping, server.sleep); } }); }) }, exited: { name: 'exited', task: server.utils.factory('server.status.exited.task', function(){ server.quit(); }) } }; //-----------------Server Methods ---------------------------------- server.runTask = server.utils.factory('server.runTask', function(status, delay){ delay = delay || 0; var type = server.CONSTANTS.Types, severity = server.CONSTANTS.Severity; if(server.current.timeout){ clearTimeout(server.current.timeout); } server.current.timeout = setTimeout(function(){ db.setServerStatus(server.serverId, status.name, function(err, rowsAffected, params){ var statusCode; if(err){ server.current.funcState = 'db.setServerStatus: Error running task'; logger.serverLog('Cannot find Oracle DB Server...', type.ERROR); server.reconnect(); }else { //run the task statusCode = params.pBSSTATUSCODE; try{ server.status[statusCode].task(); }catch(e){ server.current.funcState = 'db.setServerStatus: Error running task'; logger.fullLog(severity.ERROR, 'Invalid status ['+ statusCode +'] - '+ e, type.ERROR); server.runTask(server.status.waiting, server.sleep); } } }); }, delay); }); server.register = server.utils.factory('server.register', function(){ var serverTypes = server.CONSTANTS.Types; db.registerServer(server.hostname, function(err, rowsAffected, params){ if(err){ server.current.funcState = 'db.registerServer: Error registering server'; logger.serverLog('Could not register server', serverTypes.ERROR); server.cleanup(); server.reconnect(); }else{ if(params && params.SERVERID !== 1){ server.serverId = params.SERVERID; server.current.funcState = 'db.registerServer: Server Registered'; logger.serverLog(server.hostname +' has been registered with server id: '+ server.serverId , serverTypes.INFO); //start up the server server.runTasks(); } } }); }); server.runTasks = server.utils.factory('server.runTasks', function(){ logger.group = 'Processing Batches'; server.runTask(server.status.waiting, server.sleep); }); server.boot = server.utils.factory('server.boot', function(){ var cn = '', type = server.CONSTANTS.Types; cn = db.connect(); if(cn === ''){ server.current.funcState = 'db.connect: Server connected'; logger.serverLog('Server connected to oracle', type.INFO); server.register(); }else{ server.current.funcState = 'db.connect: Server could not connect'; logger.serverLog(cn, type.ERROR); server.reconnect(server.sleep); } }); server.reconnect = server.utils.factory('server.reconnect', function(delay){ delay = delay || 0; var o = '', type = server.CONSTANTS.Types; setTimeout(function(){ o = db.reconnect(); if(o === ''){ server.current.funcState = 'db.reconnect: Server Reconnected'; logger.serverLog('Server reconnected to oracle', type.INFO); server.register(); }else{ server.current.funcState = 'db.reconnect: Error reconnecting..'; logger.serverLog(o, type.ERROR); server.reconnect(server.sleep); } }, delay); }); server.runProcess = server.utils.factory('server.runProcess', function(callback){ var serverTypes = server.CONSTANTS.Types, severity = server.CONSTANTS.Severity, batchStatus = server.batch.STATUS; if(server.currentChildProcessCommand !== null){ server.currentChildProcess = proc.run(server.currentChildProcessCommand, function(err, stdout, stderr){ var errMessage, cbStatus, cbState, cbMessage, cbSev, cbType, success = false; logger.silent = false; if(err == null && !stderr){ server.current.funcState = 'Child process complete'; logger.fullLog(severity.INFO, stdout, serverTypes.INFO); //set the server done status cbStatus = batchStatus.DONE; cbState = 'db.setBatchStatus: Batch done'; cbMessage = 'Batch #' + server.current.batch + ' done.'; cbSev = severity.INFO; cbType = serverTypes.INFO; success = true; }else{ server.current.funcState = 'Error processing batch or batch has been killed.'; errMessage = err != null && !stderr ? 'Err [ ' + err + ' ] ' : ' Stderr [ ' + stderr + ' ] '; logger.fullLog(severity.ERROR, errMessage, serverTypes.ERROR); cbStatus = batchStatus.ERROR; cbState = 'db.setBatchStatus: Batch Error'; cbMessage = 'Error processing Batch #' + server.current.batch; cbSev = severity.ERROR; cbType = serverTypes.ERROR; success = false; } //set the batch status db.setBatchStatus(server.current.batch, cbStatus, function(){ server.current.funcState = cbState; logger.fullLog(cbSev, cbMessage, cbType); //set the status of the server db.setServerBatchDone(server.serverId, server.current.batch, function(){ server.current.funcState = 'db.setServerBatchDone: Batch Done'; logger.fullLog(severity.INFO, 'Batch Done', serverTypes.INFO); callback(success); }); }); }); //reset command after it has been launched server.currentChildProcessCommand = null; } }); server.prepareProcess = server.utils.factory('server.prepareProcess', function(callback){ var serverTypes = server.CONSTANTS.Types, severity = server.CONSTANTS.Severity, ready = false; //get the batch parameters if(!server.current.batch || server.current.batch === 0){ server.current.funcState = 'Invalid Batch'; ready = false; logger.serverLog('Invalid Batch or no batch has been set', serverTypes.ERROR); } db.getBatchParameters(server.current.batch, function(err, rowsAffected, parameters){ var exePath, args, cmd; if(err){ server.current.funcState = 'db.getBatchParameters: Error getting Batch parameters'; ready = false; logger.fullLog(severity.ERROR, err, serverTypes.ERROR); }else{ //get & prepare process parameters exePath = proc.getExecutablePath(parameters.pResultJSON.batchparameters.ApplicationKey.PVALUE); args = parameters.pResultJSON.batchparameters.CommandLineArgs.PVALUE; server.currentChildProcessCommand = proc.stringify(exePath, args); server.current.funcState = 'db.getBatchParameters: Batch parameters received, Command ready'; ready = true; logger.fullLog(severity.INFO, 'Command to be processed:\n' + server.currentChildProcessCommand, serverTypes.INFO); } callback(ready); }); }); server.killProcess = server.utils.factory('server.killProcess', function(callback){ var serverTypes = server.CONSTANTS.Types, severity = server.CONSTANTS.Severity, batchStatus = server.batch.STATUS; if(server.currentChildProcess){ proc.kill(server.currentChildProcess.pid, function(err, stdout, stderr){ var killed = false; if(err == null && !stderr && stdout){ server.current.funcState = 'Child process killed'; logger.fullLog(severity.INFO, stdout, serverTypes.WARNING); server.currentChildProcess = null; server.currentChildProcessCommand = null; killed = true; logger.fullLog(severity.INFO, 'Batch process #' + server.current.batch + ' killed.', serverTypes.WARNING); }else{ server.current.funcState = 'Error killing process'; errMessage = err != null && !stderr ? 'err: ' + err : 'std-err: ' + stderr; killed = false; logger.fullLog(severity.ERROR, errMessage, serverTypes.ERROR); } callback(killed); }); } }); server.getBatch = server.utils.factory('server.getBatch', function(callback){ var serverTypes = server.CONSTANTS.Types, severity = server.CONSTANTS.Severity, ready = false; //get the next batch db.getNextBatch(server.serverId, function(err, rowsAffected, parameters){ if(err){ server.current.funcState = 'db.getNextBatch: Error getting batch'; logger.serverLog(err, serverTypes.ERROR); } if(parameters.pBATCHID === 'null'){ server.current.funcState = 'db.getNextBatch: Waiting for a new batch'; logger.silent = true; ready = false; } else { //set the current batch and go into "processing" mode logger.silent = false; server.current.batch = parameters.pBATCHID; server.current.funcState = 'db.getNextBatch: Batch Received'; ready = true; logger.fullLog(severity.INFO, 'Server ' + server.serverId +' received batch #'+ server.current.batch + ' for processing.', serverTypes.INFO); } callback(ready); }); }); server.cleanup = server.utils.factory('server.cleanup', function(){ //kill any current process running server.killProcess(); }); server.quit = server.utils.factory('server.quit', function(){ server.cleanup(); db.dispose(); }); //---------------boot the server (entry point) ---------------------------------- server.boot();