occaecatidicta
Version:
135 lines (118 loc) • 4.44 kB
text/typescript
import { getLogger } from 'omelox-logger';
import * as utils from '../util/utils';
import * as Constants from '../util/constants';
import * as countDownLatch from '../util/countDownLatch';
import { EventEmitter } from 'events';
import * as util from 'util';
import { Application } from '../application';
import { ServerInfo } from '../util/constants';
import { ConsoleService, MasterAgent } from 'omelox-admin';
import * as path from 'path';
let logger = getLogger('omelox', path.basename(__filename));
export class Watchdog extends EventEmitter {
isStarted = false;
servers: {[serverId: string]: ServerInfo} = {};
_listeners: {[serverId: string]: number} = {};
count: number;
constructor(private app: Application, private service: ConsoleService) {
super();
this.count = Object.keys(app.getServersFromConfig()).length;
}
addServer(server: ServerInfo) {
if (!server) {
return;
}
this.servers[server.id] = server;
this.notify({ action: 'addServer', server: server });
}
removeServer(id: string) {
if (!id) {
return;
}
this.unsubscribe(id);
delete this.servers[id];
this.notify({ action: 'removeServer', id: id });
}
reconnectServer(server: ServerInfo) {
let self = this;
if (!server) {
return;
}
if (!this.servers[server.id]) {
this.servers[server.id] = server;
}
// replace server in reconnect server
this.notifyById(server.id, { action: 'replaceServer', servers: self.servers });
// notify other server to add server
this.notify({ action: 'addServer', server: server });
// add server in listener
this.subscribe(server.id);
}
subscribe(id: string) {
this._listeners[id] = 1;
}
unsubscribe(id: string) {
delete this._listeners[id];
}
query() {
return this.servers;
}
record(id: string) {
if (!this.isStarted && --this.count < 0) {
let usedTime = Date.now() - this.app.startTime;
this.notify({ action: 'startOver' });
this.isStarted = true;
logger.warn('all servers startup in %s ms', usedTime);
}
}
notifyById(id: string, msg: any) {
(this.service.agent as MasterAgent).request(id, Constants.KEYWORDS.MONITOR_WATCHER, msg, function (signal: any) {
if (signal !== Constants.SIGNAL.OK) {
logger.error('master watchdog fail to notify to monitor, id: %s, msg: %j', id, msg);
} else {
logger.debug('master watchdog notify to monitor success, id: %s, msg: %j', id, msg);
}
});
}
notify(msg: any) {
let _listeners = this._listeners;
let success = true;
let fails: string[] = [];
let timeouts: string[] = [];
let requests: {[key: string]: number} = {};
let count = Object.keys(_listeners).length;
if (count === 0) {
logger.warn('master watchdog _listeners is none, msg: %j', msg);
return;
}
let latch = countDownLatch.createCountDownLatch(count, { timeout: Constants.TIME.TIME_WAIT_COUNTDOWN }, function (isTimeout) {
if (!!isTimeout) {
for (let key in requests) {
if (!requests[key]) {
timeouts.push(key);
}
}
logger.error('master watchdog request timeout message: %j, timeouts: %j, fails: %j', msg, timeouts, fails);
}
if (!success) {
logger.error('master watchdog request fail message: %j, fails: %j', msg, fails);
}
});
let moduleRequest = function (self: Watchdog, id: string) {
return (function () {
(self.service.agent as MasterAgent).request(id, Constants.KEYWORDS.MONITOR_WATCHER, msg, function (signal: any) {
if (signal !== Constants.SIGNAL.OK) {
fails.push(id);
success = false;
}
requests[id] = 1;
latch.done();
});
})();
};
for (let id in _listeners) {
requests[id] = 0;
moduleRequest(this, id);
}
}
}