global-event-handler
Version:
A hierarchical global event handler. Runs as its own fork or standalone server and syncs events acros forks and or servers
192 lines (164 loc) • 6.17 kB
text/typescript
///<referance path="typings/node/node.d.ts"/>
export class EventKey{
public keys:{ [id: string] : EventKey; } = {};
public observers:Array<string> =[];
private suicide;
public keyId: string;
constructor(keyId?: string, suicide?:Function){
if(suicide) this.suicide = suicide;
if(keyId) this.keyId = keyId;
}
removeEventFromObservers = (eventId) =>{
var i = this.observers.indexOf(eventId);
this.observers.splice(i,1)
if(this.suicide && this.keyId && Object.keys(this.keys).length == 0 && this.observers.length == 0){
this.suicide(this.keyId);
}
}
killKey = (keyId) =>{
if(this.keys[keyId]) delete this.keys[keyId];
if(this.suicide && this.keyId && Object.keys(this.keys).length == 0 && this.observers.length == 0){
this.suicide(this.keyId);
}
}
cleanUp = () => {
if(this.suicide && this.keyId && Object.keys(this.keys).length == 0 && this.observers.length == 0){
this.suicide(this.keyId);
}
}
}
export class EventStream extends EventKey{
eventIds:{ [id: string] : {key:Object,eventKeys:Array<EventKey>,clientId:Number}; } = {};
private onEventDscrit:any = {};
onEvent = (key:Object,evPackage:Object, eventKey?:EventKey) =>{
if(!eventKey) eventKey = this;
if(eventKey === this){
this.onEventDscrit = {};
}
eventKey.observers.forEach((o)=>{
this.onEventDscrit[o] = 1;
})
for(var i in key){
if(eventKey.keys[i]) this.onEvent(key[i],evPackage,eventKey.keys[i]);
}
if(eventKey === this){
for(var i in this.onEventDscrit){
this._onNext(i,evPackage);
}
this.onEventDscrit = {};
}
}
private _onNext:Function;
public onNext = (_onNext?: (eventId:string, evPackage:any)=>any) => {
if(_onNext) this._onNext = _onNext;
}
addEvent = (clientId:Number, eventId:string,key?:Object) => {
this.eventIds[eventId] = {clientId:clientId,key:key || {},eventKeys:[]};
this.addKey(this,eventId,key);
}
addKey = (parent:EventKey, eventId:string,key?:Object) => {
if(!key || Object.keys(key).length == 0){
this.observers.push(eventId);
this.eventIds[eventId].eventKeys.push(parent)
}
else
for(var i in key){
if(!parent.keys[i]) parent.keys[i] = new EventKey(i,parent.killKey);
if(Object.keys(key[i]).length == 0){
parent.keys[i].observers.push(eventId);
this.eventIds[eventId].eventKeys.push(parent.keys[i]);
}
else{
this.addKey(parent.keys[i],eventId,key[i]);
}
}
}
removeEvent = (eventId:string) => {
if(this.eventIds[eventId]){
this.eventIds[eventId].eventKeys.forEach(function(eventKey){
eventKey.removeEventFromObservers(eventId)
})
delete this.eventIds[eventId];
}
}
removeClient = (clientId:Number) => {
for(var i in this.eventIds){
if(this.eventIds[i].clientId === clientId){
this.removeEvent(i);
}
}
}
}
export class globalEventHandlerServer {
constructor(public port){
var net = require('net'),
JsonSocket = require('json-socket');
var now = require("performance-now")
let eventMan:EventStream = new EventStream('global');
var server = net.createServer();
server.listen(this.port);
var lastSocketId = 0;
var sockets = {};
var stats = {in:0,out:0, timeSpan:0}, statStartTime = now();
// setInterval(function(){
// var timeSpan = (now()-statStartTime)/1000;
// stats.out = stats.out/timeSpan;
// stats.in = stats.in/timeSpan;
// stats.timeSpan = timeSpan;
// console.log(stats);
// stats = {in:0,out:0, timeSpan:0};
// statStartTime = now()
// },10000)
eventMan.onNext(function(eventId,evPackage){
stats.out++;
var sId = eventId, dotIndex = sId.indexOf(".");
sId = sId.slice(0, dotIndex);
eventId = eventId.substr(dotIndex + 1);
var socket = sockets[sId];
socket.sendMessage({eventId: eventId, evPackage:evPackage});
})
server.on('connection', function(socket) { //This is a standard net.Socket
//console.log('connected');
socket = new JsonSocket(socket); //Now we've decorated the net.Socket to be a JsonSocket test
lastSocketId++;
sockets[lastSocketId] = socket;
socket.socketsId = lastSocketId;
socket.on('message', function(message) {
//console.log(message);
switch (message.type)
{
case 'addEvent':
eventMan.addEvent(socket.socketsId, socket.socketsId.toString() + '.' + message.eventId, message.key);
break;
case 'onEvent':
stats.in++;
eventMan.onEvent(message.key,message.evPackage,eventMan);
break;
case 'removeEvent':
eventMan.removeEvent(socket.socketsId.toString() + '.' + message.eventId);
break;
}
});
socket.on('error', function (exc) {
console.log("ignoring exception: " + exc);
if(exc = 'Error: read ECONNRESET'){
eventMan.removeClient(socket.socketsId);
delete sockets[socket.socketsId];
}
});
socket.on('disconnect',function(){
eventMan.removeClient(socket.socketsId);
delete sockets[socket.socketsId];
})
});
}
}
var on = false
process.on('message', function(msg) {
//console.log('Worker ' + process.pid + ' received message from master.', msg);
if(on == false && (msg.data && (msg.data == 'connect' || msg.data.event == 'connect')) || (msg.event == 'connect')){
on = true;
var gehTestServer = new globalEventHandlerServer(9838) ;
}
console.log('connetting')
});