UNPKG

activestack-gateway

Version:
189 lines (163 loc) 6.29 kB
'use strict'; module.exports = GatewayWorker; function GatewayWorker(){ this.logger = null; this.properties = null; this.currentClientQueueLength = 0; this.exiting = false; this.restartOnClientQueueEmpty = false; this.stopOnClientQueueEmpty = false; } GatewayWorker.prototype.inject = function(prefixedLogger, properties, gateway){ this.logger = prefixedLogger; this.properties = properties; this.gateway = gateway; }; GatewayWorker.prototype.isExiting = function(){ return this.exiting; }; GatewayWorker.prototype.checkMemoryUsage = function () { var memoryUsage = process.memoryUsage(); var megabyte = 1024 * 1024; for (var type in memoryUsage) { var limit = this.properties['cluster.memoryLimit.' + type]; var warning = this.properties['cluster.memoryWarning.' + type]; if (limit && (memoryUsage[type] > limit * megabyte)) { this.logger.error('Worker exceeded hard ' + type + ' memory limit (' + memoryUsage[type] + '/' + limit * megabyte + ')!'); } } }; GatewayWorker.prototype.sendMessage = function(message) { this.logger.debug('Received message from service'); if (message) { if (message.command === 'clientQueueLength') { this.currentClientQueueLength = message.data; if (this.restartOnClientQueueEmpty && this.currentClientQueueLength <= 0) { this.logger.info('Client Queue is Empty: RESTARTING'); process.send({command: 'restart'}); } else if (this.stopOnClientQueueEmpty && this.currentClientQueueLength <= 0) { this.logger.info('Client Queue is Empty: STOPPING'); process.send({command: 'stop'}); } } } }; GatewayWorker.prototype.onMessageStopOrRestart = function(msg){ var cmd = msg.cmd; var type = msg.type; var data = parseInt(msg.data); this.logger.info('server received '+msg.cmd+' message: ' + type); if (type.toLowerCase() === 'on_client_queue_empty') { this.gateway.onShutdown(type); if (this.currentClientQueueLength <= 0) { process.send({command: cmd}); } else { if(cmd == 'stop') this.stopOnClientQueueEmpty = true; else if(cmd == 'restart') this.restartOnClientQueueEmpty = true; if (data) { // Set the timeout to restart this server process. this.logger.info(cmd+' request received. ' + this.currentClientQueueLength + ' client(s) currently connected. Setting '+cmd+' timeout to ' + data); setTimeout(function () { this.logger.warn('Server '+cmd+' timeout, stopping process with ' + this.currentClientQueueLength + ' connected client(s)'); process.send({command: cmd}); }.bind(this), data); } } } else { process.send({command: cmd}); } }; GatewayWorker.prototype.onMessageLogLevel = function(msg){ throw new Error('NOT IMPLEMENTED'); //var logLevel = msg.data; //this.logger.info('Setting LogLevel to ' + logLevel); //logger.remove(winston.transports.Console); //logger.add(winston.transports.Console, {level: logLevel}); }; GatewayWorker.prototype.onMessageCMSI = function(msg){ var clientMessageResendInterval = msg.data; this.logger.info('Setting clientMessageResendInterval to ' + clientMessageResendInterval); this.properties['frontend.clientMessageResendInterval'] = clientMessageResendInterval; }; GatewayWorker.prototype.onMessageClientCount = function(msg){ this.logger.info('Getting clientCount: ' + this.currentClientQueueLength + ' client(s) currently connected'); process.send({command: 'clientCount', data: this.currentClientQueueLength}); }; GatewayWorker.prototype.onProcessMessage = function (msg) { var command = msg.cmd.toLowerCase(); switch(command){ case 'restart': this.onMessageStopOrRestart(msg); break; case 'stop': this.onMessageStopOrRestart(msg); break; case 'loglevel': this.onMessageLogLevel(msg); break; case 'clientmessageresendinterval': this.onMessageCMSI(msg); break; case 'clientcount': this.onMessageClientCount(msg); break; default: this.logger.info('server received unknown message: ' + JSON.stringify(msg)); break; } }; GatewayWorker.prototype.createErrorHandler = function createErrorHandler(source) { return function (error) { if (error.stack) { this.logger.error('Fatal ' + source + ' error: ', error.stack); } else { this.logger.error('Fatal ' + source + ' error: ', JSON.stringify(error)); } clearInterval(this.heartbeat); if (process.send && !this.exiting) { this.catchAndWarn('master communication channel', function () { process.send({command: 'disconnect'}); }); } this.gateway.handleError(error, source); this.exiting = true; }.bind(this); }; GatewayWorker.prototype.catchAndWarn = function catchAndWarn(connection, cleanup) { try { cleanup(); } catch (error) { if (this && !this.exiting) { this.logger.warn('Error disconnecting ' + connection + ' (' +error.toString() + ')'); } } }; GatewayWorker.prototype.startHeartbeartPoller = function(){ if (process.send) { this.heartbeat = setInterval(function () { process.send({command: 'heartbeat', memory: process.memoryUsage()}); }, this.properties['cluster.heartbeatInterval']); } }; GatewayWorker.prototype.startMemoryUsagePoller = function(){ setInterval(function () { try { this.checkMemoryUsage(); } catch (error) { this.logger.info(error); } }.bind(this), 1000); }; GatewayWorker.prototype.start = function() { process.on('message', this.onProcessMessage.bind(this)); this.startHeartbeartPoller(); this.startMemoryUsagePoller(); this.gateway.start(); };