adapting bridge

This commit is contained in:
Martin Karkowski 2021-03-22 19:02:24 +01:00
parent 768d21f63c
commit 3742062684
2 changed files with 114 additions and 8 deletions

View File

@ -64,7 +64,7 @@ export class IoSocketClient extends Bridge implements ICommunicationInterface {
? new EventLayer(socket as any, this._logger) ? new EventLayer(socket as any, this._logger)
: new MirrorLayer(socket as any, this._logger); : new MirrorLayer(socket as any, this._logger);
// 3. Add the Layer // 3. Add the Layer
this.addLayer(layer); this.addLayer(layer, true, true);
socket.on("connect", (...args) => { socket.on("connect", (...args) => {
// Assign new ID. // Assign new ID.

View File

@ -10,12 +10,14 @@ import { EventEmitter } from "events";
import * as Logger from "js-logger"; import * as Logger from "js-logger";
import { ILogger } from "js-logger"; import { ILogger } from "js-logger";
import { generateId } from "../helpers/idMethods"; import { generateId } from "../helpers/idMethods";
import { copy } from "../helpers/objectMethods";
import { getNopeLogger } from "../logger/getLogger"; import { getNopeLogger } from "../logger/getLogger";
import { LoggerLevel } from "../logger/nopeLogger"; import { LoggerLevel } from "../logger/nopeLogger";
import { NopeObservable } from "../observables/nopeObservable"; import { NopeObservable } from "../observables/nopeObservable";
import { import {
ICommunicationBridge, ICommunicationBridge,
ICommunicationInterface ICommunicationInterface,
IEmitter
} from "../types/nope/nopeCommunication.interface"; } from "../types/nope/nopeCommunication.interface";
import { INopeObservable } from "../types/nope/nopeObservable.interface"; import { INopeObservable } from "../types/nope/nopeObservable.interface";
@ -83,6 +85,30 @@ const METHOD_TO_EVENT: { [P in keyof ICommunicationInterface]: string } = {
emitRpcResponse: "" emitRpcResponse: ""
}; };
const MIRROR_METHOD_MAPPING = copy(METHOD_TO_EVENT);
MIRROR_METHOD_MAPPING.onEvent = "event";
MIRROR_METHOD_MAPPING.emitEvent = "event";
MIRROR_METHOD_MAPPING.onRpcRequest = "rpcRequest";
MIRROR_METHOD_MAPPING.emitRpcRequest = "rpcRequest";
MIRROR_METHOD_MAPPING.onRpcRequest = "rpcResponse";
MIRROR_METHOD_MAPPING.emitRpcRequest = "rpcResponse";
const MIRROR_EVENT_TO_EMIT: {
[index: string]: keyof ICommunicationInterface;
} = {};
// Define all Events, that must be considered in a mirror.
const MIRROR_EVENTS = new Set(
Object.getOwnPropertyNames(MIRROR_METHOD_MAPPING).map((method) => {
if (method.startsWith("emit")) {
MIRROR_EVENT_TO_EMIT[
MIRROR_METHOD_MAPPING[method]
] = method as keyof ICommunicationInterface;
}
return MIRROR_METHOD_MAPPING[method];
})
);
const OFF_METHODS: Array<keyof ICommunicationInterface> = [ const OFF_METHODS: Array<keyof ICommunicationInterface> = [
"offEvent", "offEvent",
"offRpcRequest", "offRpcRequest",
@ -131,6 +157,8 @@ export class Bridge implements ICommunicationBridge {
} }
>; >;
protected _mirrors: Set<IEmitter>;
protected _callbacks: Map< protected _callbacks: Map<
string, // Method string, // Method
Array<(...args) => any> Array<(...args) => any>
@ -158,6 +186,7 @@ export class Bridge implements ICommunicationBridge {
this._callbacks = new Map(); this._callbacks = new Map();
this._specificCallbacks = []; this._specificCallbacks = [];
this._layers = new Map(); this._layers = new Map();
this._mirrors = new Set();
this._logger = getNopeLogger(loggerName, level); this._logger = getNopeLogger(loggerName, level);
this.id = id; this.id = id;
@ -183,12 +212,12 @@ export class Bridge implements ICommunicationBridge {
} }
for (const method of EMITTING_METHODS) { for (const method of EMITTING_METHODS) {
this[method] = async (data) => { this[method] = async (data) => {
_this._emit(method, data); _this._emit(method, null, data);
}; };
} }
for (const method of EMITTING_SPECIFIC_METHODS) { for (const method of EMITTING_SPECIFIC_METHODS) {
this[method] = (event: string, data) => { this[method] = async (event: string, data) => {
_this._emitSpecific(method, event, data); _this._emitSpecific(method, null, event, data);
}; };
} }
@ -224,7 +253,7 @@ export class Bridge implements ICommunicationBridge {
// Iterate over the layers and forward the Data to the other Layers // Iterate over the layers and forward the Data to the other Layers
for (const data of this._layers.values()) { for (const data of this._layers.values()) {
if (data.layer !== layerToExclude) { if (data.layer !== layerToExclude) {
data.layer[method as any](...args).catch((error) => { data.layer[MAPPING_METHODS[method] as any](...args).catch((error) => {
this._logger.error("failed forwarding", method, ...args); this._logger.error("failed forwarding", method, ...args);
this._logger.error(error); this._logger.error(error);
}); });
@ -333,6 +362,7 @@ export class Bridge implements ICommunicationBridge {
this._internalEmitter.setMaxListeners( this._internalEmitter.setMaxListeners(
this._internalEmitter.getMaxListeners() + 1 this._internalEmitter.getMaxListeners() + 1
); );
if (this._logger.enabledFor(Logger.DEBUG) && event !== "StatusUpdate") { if (this._logger.enabledFor(Logger.DEBUG) && event !== "StatusUpdate") {
this._logger.debug("subscribe ", method, "specifically on", eventToUse); this._logger.debug("subscribe ", method, "specifically on", eventToUse);
@ -379,6 +409,7 @@ export class Bridge implements ICommunicationBridge {
protected _emit( protected _emit(
method: keyof ICommunicationInterface, method: keyof ICommunicationInterface,
toExclude: ICommunicationInterface | IEmitter = null,
dataToSend: any dataToSend: any
): void { ): void {
const event = METHOD_TO_EVENT[method]; const event = METHOD_TO_EVENT[method];
@ -395,17 +426,25 @@ export class Bridge implements ICommunicationBridge {
// Iterate over the Layers. // Iterate over the Layers.
for (const data of this._layers.values()) { for (const data of this._layers.values()) {
// If the Layer has been conneced // If the Layer has been conneced
if (data.layer.connected.getContent()) { if (data.layer !== toExclude && data.layer.connected.getContent()) {
// Only Publish the Data, on which we are forwarding
data.layer[method as any](dataToSend).catch((error) => { data.layer[method as any](dataToSend).catch((error) => {
_this._logger.error("failed executing", method); _this._logger.error("failed executing", method);
_this._logger.error(error); _this._logger.error(error);
}); });
} }
} }
for (const mirror of this._mirrors) {
if (mirror != toExclude) {
mirror.emit(MIRROR_METHOD_MAPPING[method], dataToSend);
}
}
} }
protected _emitSpecific( protected _emitSpecific(
method: keyof ICommunicationInterface, method: keyof ICommunicationInterface,
toExclude: ICommunicationInterface | IEmitter = null,
event: string, event: string,
dataToSend: any dataToSend: any
): void { ): void {
@ -425,13 +464,22 @@ export class Bridge implements ICommunicationBridge {
// Iterate over the Layers. // Iterate over the Layers.
for (const data of this._layers.values()) { for (const data of this._layers.values()) {
// If the Layer has been conneced // If the Layer has been conneced
if (data.layer.connected.getContent()) { if (data.layer !== toExclude && data.layer.connected.getContent()) {
data.layer[method as any](event, dataToSend).catch((error) => { data.layer[method as any](event, dataToSend).catch((error) => {
_this._logger.error("failed executing", method); _this._logger.error("failed executing", method);
_this._logger.error(error); _this._logger.error(error);
}); });
} }
} }
for (const mirror of this._mirrors) {
if (mirror != toExclude) {
mirror.emit(MIRROR_METHOD_MAPPING[method], {
name: event,
data: dataToSend
});
}
}
} }
public async addLayer( public async addLayer(
@ -477,4 +525,62 @@ export class Bridge implements ICommunicationBridge {
this._layers.delete(layer.id); this._layers.delete(layer.id);
} }
} }
/**
* Adds a Mirror to the System.
*
* @param {IEmitter} mirror
* @return {*} {Promise<void>}
* @memberof Bridge
*/
public addMirror(mirror: IEmitter, addSubscriptions = true): void {
if (!this._mirrors.has(mirror)) {
this._mirrors.add(mirror);
if (addSubscriptions) {
const _this = this;
for (const eventName of MIRROR_EVENTS) {
if (!ON_SPECIFIC_METHODS.includes(eventName)) {
mirror.on(eventName, (data) => {
if (
_this._logger.enabledFor(Logger.DEBUG) &&
eventName !== "StatusUpdate"
) {
_this._logger.debug("received data from mirror on", eventName);
}
_this._emit(MIRROR_EVENT_TO_EMIT[eventName], mirror, data);
});
} else {
mirror.on(eventName, (data) => {
// If logging is enabled => Forward this information
if (
_this._logger.enabledFor(Logger.DEBUG) &&
eventName !== "StatusUpdate"
) {
_this._logger.debug(
"received data from mirror on",
eventName,
data.name
);
}
// Now emit the data on the channel
_this._emitSpecific(
MIRROR_EVENT_TO_EMIT[eventName],
mirror,
data.name,
data.data
);
});
}
}
}
}
}
public removeMirror(mirror: IEmitter): boolean {
return this._mirrors.delete(mirror);
}
} }