happn-3
Version:
pub/sub api as a service using primus and mongo & redis or nedb, can work as cluster, single process or embedded using nedb
200 lines (161 loc) • 5.61 kB
JavaScript
var shortid = require('shortid'),
sillyname = require('happn-sillyname'),
CONSTANTS = require('../../constants');
module.exports = SystemService;
function SystemService(opts) {
this.log = opts.logger.createLogger('System');
this.log.$$TRACE('construct(%j)', opts);
Object.defineProperty(this, 'package', {
value: require('../../../package.json')
});
this.resetStats();
}
SystemService.prototype.resetStats = function() {
this.__stats = {
HEALTH: {
STATUS: CONSTANTS.SYSTEM_HEALTH.EXCELLENT,
BY_SEVERITY: {},
BY_AREA: {}
}
};
for (var severity in CONSTANTS.ERROR_SEVERITY) {
this.__stats.HEALTH.BY_SEVERITY[CONSTANTS.ERROR_SEVERITY[severity]] = 0;
}
this.__stats.HEALTH.lastError = null;
};
SystemService.prototype.stats = function() {
var stats = JSON.parse(JSON.stringify(this.__stats));
stats.memory = process.memoryUsage();
return stats;
};
SystemService.prototype.uniqueName = function() {
return (
sillyname()
.split(' ')[0]
.toLowerCase() +
'_' +
shortid.generate()
);
};
SystemService.prototype._ensureSystemName = function(config, callback) {
var _this = this;
_this.dataService.get('/_SYSTEM/_NETWORK/_SETTINGS/NAME', {}, function(e, response) {
if (e) return callback(e);
if (!response) {
if (!config.name) config.name = _this.uniqueName();
return _this.dataService.upsert('/_SYSTEM/_NETWORK/_SETTINGS/NAME', config.name, {}, function(
e,
result
) {
if (e) return callback(e);
_this.name = result.data.value;
_this.happn.name = result.data.value;
callback();
});
} else {
if (config.name && response.data.value !== config.name) {
return _this.dataService.upsert(
'/_SYSTEM/_NETWORK/_SETTINGS/NAME',
config.name,
{},
function(e, result) {
if (e) return callback(e);
_this.name = result.data.value;
_this.happn.name = result.data.value;
callback();
}
);
} else {
_this.name = response.data.value;
_this.happn.name = response.data.value;
}
}
callback();
});
};
SystemService.prototype.processMessage = function(message) {
if (message.request.action === 'describe')
message.response = {
data: this.getDescription(message)
};
return message;
};
SystemService.prototype.logError = function(e, area, severity) {
if (!area) area = 'System';
if (!severity) severity = CONSTANTS.ERROR_SEVERITY.LOW;
this.__stats.HEALTH.BY_SEVERITY[severity]++;
this.__stats.HEALTH.lastError = {
message: e.toString(),
area: area,
severity: severity
};
if (!this.__stats.HEALTH.BY_AREA[area]) this.__stats.HEALTH.BY_AREA[area] = 0;
this.__stats.HEALTH.BY_AREA[area] += severity;
if (this.__stats.HEALTH.STATUS === CONSTANTS.SYSTEM_HEALTH.EXCELLENT) {
if (severity === CONSTANTS.ERROR_SEVERITY.LOW)
this.__stats.HEALTH.STATUS = CONSTANTS.SYSTEM_HEALTH.FAIR;
if (severity === CONSTANTS.ERROR_SEVERITY.MEDIUM)
this.__stats.HEALTH.STATUS = CONSTANTS.SYSTEM_HEALTH.TAKING_STRAIN;
if (severity === CONSTANTS.ERROR_SEVERITY.HIGH || severity === CONSTANTS.ERROR_SEVERITY.FATAL)
this.__stats.HEALTH.STATUS = CONSTANTS.SYSTEM_HEALTH.POOR;
} else if (this.__stats.HEALTH.STATUS === CONSTANTS.SYSTEM_HEALTH.FAIR) {
if (severity === CONSTANTS.ERROR_SEVERITY.MEDIUM)
this.__stats.HEALTH.STATUS = CONSTANTS.SYSTEM_HEALTH.TAKING_STRAIN;
if (severity === CONSTANTS.ERROR_SEVERITY.HIGH || severity === CONSTANTS.ERROR_SEVERITY.FATAL)
this.__stats.HEALTH.STATUS = CONSTANTS.SYSTEM_HEALTH.POOR;
} else if (this.__stats.HEALTH.STATUS === CONSTANTS.SYSTEM_HEALTH.TAKING_STRAIN) {
if (severity === CONSTANTS.ERROR_SEVERITY.HIGH || severity === CONSTANTS.ERROR_SEVERITY.FATAL)
this.__stats.HEALTH.STATUS = CONSTANTS.SYSTEM_HEALTH.POOR;
}
};
SystemService.prototype.getDescription = function(message) {
var description = {
name: this.name,
secure: this.happn.config.secure ? true : false,
encryptPayloads: this.happn.config.encryptPayloads ? true : false
};
if (message && message.session.cookieName) description.cookieName = message.session.cookieName;
if (this.happn.services.security._keyPair)
description.publicKey = this.happn.services.security._keyPair.publicKey;
return description;
};
SystemService.prototype.__processSystemMessage = function(message) {
try {
if (message.action === 'MEMORY_USAGE') {
message.response = process.memoryUsage();
}
if (message.action === 'STATS') {
message.response = this.stats();
}
if (message.action === 'GC') {
if (!global.gc) {
message.response = 'GC NOT ENABLED';
} else {
global.gc();
message.response = 'DONE';
}
}
} catch (e) {
message.response = 'ERROR: ' + e.toString();
}
process.send(message);
};
SystemService.prototype.stop = function(options, callback) {
if (typeof options === 'function') callback = options;
process.removeAllListeners('message');
callback();
};
SystemService.prototype.initialize = function(config, callback) {
process.on('message', this.__processSystemMessage.bind(this));
this.config = config;
this.dataService = this.happn.services.data;
this._ensureSystemName(
config,
function(e) {
if (e) return callback(e);
this.log.info('instance name: ' + this.name);
this.log.context = this.name;
callback();
}.bind(this)
);
};