Files
Superalgos/EventsServer/server.js
T

250 lines
11 KiB
JavaScript

/* Callbacks default responses. */
global.DEFAULT_OK_RESPONSE = {
result: "Ok",
message: "Operation Succeeded"
};
global.DEFAULT_FAIL_RESPONSE = {
result: "Fail",
message: "Operation Failed"
};
var ipc = require('node-ipc');
ipc.config.id = 'world';
ipc.config.retry = 1500;
ipc.config.silent = true;
let eventHandlers = new Map()
let counter = 0
ipc.serve(
function () {
ipc.server.on(
'message',
function (data, socket) {
ipc.log('[INFO] Events Server -> Got a new message : '.debug, data);
try {
let command = JSON.parse(data)
switch (command.action) {
case "greetings": {
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "createEventHandler": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
/*
We will only create event handlers which were not created before. Remember that someone trying to listen events
at an event handler that does not exist, will create that eventhandler, so it is possible that the emitter
when trying to create the event handler in fact was late and the event handler is already there if the listener
arrived here first. An event handler created with this method is not destroyed if there are no listeners or they
all leave.
*/
eventHandler = newEventHandler()
eventHandler.deleteWhenAllListenersAreGone = false
eventHandlers.set(command.eventHandlerName, eventHandler)
}
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "deleteEventHandler": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler !== undefined) {
/*
We will only delete event handlers which have noone listening, allowing a listener to continue listening even
when the event emitter is gone, asuming that it could come back at some point in time and resume emitting.
*/
if (eventHandler.listeners.length === 0) {
eventHandlers.delete(command.eventHandlerName)
} else {
eventHandler.deleteWhenAllListenersAreGone = true
}
}
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "listenToEvent": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
/*
We will create event handlers which were not created before if a listener tries to listen to a handler that does noet
exist before the emitter comes and create it. This is to aviod syncronization problems and also problems with emitters life
cycles with higher frecuency that the ones of listeners. Created in this way, event handlers are marked for deletion if
all listeners stop listening at one point in time.
*/
eventHandler = newEventHandler()
eventHandler.deleteWhenAllListenersAreGone = true
eventHandlers.set(command.eventHandlerName, eventHandler)
}
eventSubscriptionId = eventHandler.listenToEvent(command.eventHandlerName, command.eventType, command.callerId, handlerFunction, command.extraData)
function handlerFunction(event, extraData) {
let outputData = {
action: 'Event Raised',
eventHandlerName: command.eventHandlerName,
eventType: command.eventType,
event: event,
callerId: command.callerId,
extraData: extraData
}
ipc.server.emit(
socket,
'message',
JSON.stringify(outputData)
);
}
let response = {
result: global.DEFAULT_OK_RESPONSE.result,
message: global.DEFAULT_OK_RESPONSE.message,
eventSubscriptionId: eventSubscriptionId
}
sendResponse(response)
return
}
case "stopListening": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
if (ipc.config.silent !== true) {
console.log("[WARN] Events Server -> Cannot to stop listening to events at an Event Handler that does not exist. Command = "+ JSON.stringify(command))
}
sendResponse(global.DEFAULT_FAIL_RESPONSE)
return
}
eventHandler.stopListening(command.eventHandlerName, command.eventType, command.callerId, command.eventSubscriptionId)
/*
We check here if there are no more listeners and the event handler original emmiter is also gone, then we need to delete
this event handlers since chances are that is not needed anymore.
*/
if (eventHandler.listeners.length === 0 && eventHandler.deleteWhenAllListenersAreGone === true) {
eventHandlers.delete(command.eventHandlerName)
}
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "raiseEvent": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
if (ipc.config.silent !== true) {
console.log("[WARN] Events Server -> Cannot raise events at an Event Handler that does not exist. Command = " + JSON.stringify(command))
}
sendResponse(global.DEFAULT_FAIL_RESPONSE)
return
}
//console.log("[INFO] Events Server -> Raising Event " + command.eventHandlerName + " " + command.eventType)
eventHandler.raiseEvent(command.eventType, command.event)
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
}
console.log("[WARN] Events Server -> Unknown Command Received:" + data)
function sendResponse(message) {
if (command.callerId) {
message.callerId = command.callerId
}
message.action = 'Event Server Response'
ipc.server.emit(
socket,
'message',
JSON.stringify(message)
);
}
} catch (err) {
console.log("[ERROR] Events Server -> Bad Command Received:" + data)
console.log("[ERROR] Events Server -> An Error Happened:" + err.stack)
sendResponse(global.DEFAULT_FAIL_RESPONSE)
}
}
);
ipc.server.on(
'connect',
function (socket) {
ipc.log('[INFO] Events Server -> client has connected!');
}
);
ipc.server.on(
'socket.disconnected',
function (socket) {
ipc.log('[INFO] Events Server -> client has disconnected!');
}
);
}
);
ipc.server.start();
console.log('Events Server Started.')
function newEventHandler() {
let thisObject = {
name: undefined, // This is for debugging purposes only.
deleteWhenAllListenersAreGone: false,
listeners: [], // Here we store all the functions we will call when an event is raiseed.
listenToEvent: listenToEvent,
stopListening: stopListening,
raiseEvent: raiseEvent,
finalize: finalize
}
return thisObject
function finalize() {
thisObject.listeners = []
}
function listenToEvent(eventHandlerName, eventType, callerId, handler, extraData) {
let eventSubscriptionId = Math.trunc(Math.random() * 1000000)
thisObject.listeners.push([eventHandlerName, eventType, callerId, handler, extraData, eventSubscriptionId])
return eventSubscriptionId
}
function stopListening(eventHandlerName, eventType, callerId, eventSubscriptionId) {
if (eventSubscriptionId !== undefined) {
for (let i = 0; i < thisObject.listeners.length; i++) {
if (eventSubscriptionId === thisObject.listeners[i][5]) {
thisObject.listeners.splice(i, 1)
return
}
}
}
if (eventHandlerName !== undefined && eventType !== undefined && callerId !== undefined) {
for (let i = 0; i < thisObject.listeners.length; i++) {
if (eventHandlerName === thisObject.listeners[i][0] && eventType === thisObject.listeners[i][1] && callerId === thisObject.listeners[i][2]) {
thisObject.listeners.splice(i, 1)
return
}
}
}
}
function raiseEvent(eventType, event) {
for (let i = 0; i < thisObject.listeners.length; i++) {
/* We will execute all the functions listening to this event type. */
if (thisObject.listeners[i][1] === eventType) {
let handler = thisObject.listeners[i][3]
let extraData = thisObject.listeners[i][4]
handler(event, extraData)
}
}
}
}