pomelo-admin1312
Version:
`pomelo-admin1312` is an admin console library for [pomelo](https://github.com/NetEase/pomelo). It provides the a series of utilities to monitor the `pomelo` server clusters.
237 lines (213 loc) • 6.32 kB
JavaScript
var logger = require('pomelo-logger').getLogger('pomelo-admin', 'MonitorAgent');
var MqttClient = require('../protocol/mqtt/mqttClient');
var EventEmitter = require('events').EventEmitter;
var protocol = require('../util/protocol');
var utils = require('../util/utils');
var Util = require('util');
var ST_INITED = 1;
var ST_CONNECTED = 2;
var ST_REGISTERED = 3;
var ST_CLOSED = 4;
var STATUS_INTERVAL = 5 * 1000; // 60 seconds
/**
* MonitorAgent Constructor
*
* @class MasterAgent
* @constructor
* @param {Object} opts construct parameter
* opts.consoleService {Object} consoleService
* opts.id {String} server id
* opts.type {String} server type, 'master', 'connector', etc.
* opts.info {Object} more server info for current server, {id, serverType, host, port}
* @api public
*/
var MonitorAgent = function(opts) {
EventEmitter.call(this);
this.reqId = 1;
this.opts = opts;
this.id = opts.id;
this.socket = null;
this.callbacks = {};
this.type = opts.type;
this.info = opts.info;
this.state = ST_INITED;
this.consoleService = opts.consoleService;
};
Util.inherits(MonitorAgent, EventEmitter);
/**
* register and connect to master server
*
* @param {String} port
* @param {String} host
* @param {Function} cb callback function
* @api public
*/
MonitorAgent.prototype.connect = function(port, host, cb) {
if (this.state > ST_INITED) {
logger.error('monitor client has connected or closed.');
return;
}
cb = cb || function() {}
this.socket = new MqttClient(this.opts);
this.socket.connect(host, port);
// this.socket = sclient.connect(host + ':' + port, {
// 'force new connection': true,
// 'reconnect': true,
// 'max reconnection attempts': 20
// });
var self = this;
this.socket.on('register', function(msg) {
if (msg && msg.code === protocol.PRO_OK) {
self.state = ST_REGISTERED;
cb();
} else {
self.emit('close');
logger.error('server %j %j register master failed', self.id, self.type);
}
});
this.socket.on('monitor', function(msg) {
if (self.state !== ST_REGISTERED) {
return;
}
msg = protocol.parse(msg);
if (msg.command) {
// a command from master
self.consoleService.command(msg.command, msg.moduleId, msg.body, function(err, res) {
//notify should not have a callback
});
} else {
var respId = msg.respId;
if (respId) {
// a response from monitor
var respCb = self.callbacks[respId];
if (!respCb) {
logger.warn('unknown resp id:' + respId);
return;
}
delete self.callbacks[respId];
respCb(msg.error, msg.body);
return;
}
// request from master
self.consoleService.execute(msg.moduleId, 'monitorHandler', msg.body, function(err, res) {
if (protocol.isRequest(msg)) {
var resp = protocol.composeResponse(msg, err, res);
if (resp) {
self.doSend('monitor', resp);
}
} else {
//notify should not have a callback
logger.error('notify should not have a callback.');
}
});
}
});
this.socket.on('connect', function() {
if (self.state > ST_INITED) {
//ignore reconnect
return;
}
self.state = ST_CONNECTED;
var req = {
id: self.id,
type: 'monitor',
serverType: self.type,
pid: process.pid,
info: self.info
};
var authServer = self.consoleService.authServer;
var env = self.consoleService.env;
authServer(req, env, function(token) {
req['token'] = token;
self.doSend('register', req);
});
});
this.socket.on('error', function(err) {
if (self.state < ST_CONNECTED) {
// error occurs during connecting stage
cb(err);
} else {
self.emit('error', err);
}
});
this.socket.on('disconnect', function(reason) {
self.state = ST_CLOSED;
self.emit('close');
});
this.socket.on('reconnect', function() {
self.state = ST_CONNECTED;
var req = {
id: self.id,
type: 'monitor',
info: self.info,
pid: process.pid,
serverType: self.type
};
self.doSend('reconnect', req);
});
this.socket.on('reconnect_ok', function(msg) {
if (msg && msg.code === protocol.PRO_OK) {
self.state = ST_REGISTERED;
}
});
};
/**
* close monitor agent
*
* @api public
*/
MonitorAgent.prototype.close = function() {
if (this.state >= ST_CLOSED) {
return;
}
this.state = ST_CLOSED;
this.socket.disconnect();
};
/**
* set module
*
* @param {String} moduleId module id/name
* @param {Object} value module object
* @api public
*/
MonitorAgent.prototype.set = function(moduleId, value) {
this.consoleService.set(moduleId, value);
};
/**
* get module
*
* @param {String} moduleId module id/name
* @api public
*/
MonitorAgent.prototype.get = function(moduleId) {
return this.consoleService.get(moduleId);
};
/**
* notify master server without callback
*
* @param {String} moduleId module id/name
* @param {Object} msg message
* @api public
*/
MonitorAgent.prototype.notify = function(moduleId, msg) {
if (this.state !== ST_REGISTERED) {
logger.error('agent can not notify now, state:' + this.state);
return;
}
this.doSend('monitor', protocol.composeRequest(null, moduleId, msg));
// this.socket.emit('monitor', protocol.composeRequest(null, moduleId, msg));
};
MonitorAgent.prototype.request = function(moduleId, msg, cb) {
if (this.state !== ST_REGISTERED) {
logger.error('agent can not request now, state:' + this.state);
return;
}
var reqId = this.reqId++;
this.callbacks[reqId] = cb;
this.doSend('monitor', protocol.composeRequest(reqId, moduleId, msg));
// this.socket.emit('monitor', protocol.composeRequest(reqId, moduleId, msg));
};
MonitorAgent.prototype.doSend = function(topic, msg) {
this.socket.send(topic, msg);
}
module.exports = MonitorAgent;