nope-js-browser
Version:
NoPE Runtime for the Browser. For nodejs please use nope-js-node
131 lines (130 loc) • 5.65 kB
JavaScript
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2022-01-06 07:15:22
* @modify date 2022-01-06 09:03:30
* @desc [description]
*/
import { registerGarbageCallback } from "../../helpers/gc";
import { generateId } from "../../helpers/idMethods";
import { defineNopeLogger } from "../../logger/getLogger";
import { INFO } from "../../logger/index.browser";
import { DataPubSubSystem, PubSubSystem } from "../../pubSub";
import { NopeConnectivityManager } from "../ConnectivityManager";
import { NopeInstanceManager, } from "../InstanceManager";
import { generateSelector, NopeRpcManager } from "../RpcManager";
export class NopeCore {
constructor(options, generateEmitter, generateObservable, id = null) {
var _a;
this.options = options;
this.generateEmitter = generateEmitter;
this.generateObservable = generateObservable;
this.id = id;
// Store the communicator:
this.communicator = options.communicator;
if (id == null) {
if (options.id) {
this.id = options.id;
}
else {
this.id = generateId();
}
}
this._logger = defineNopeLogger(options.logger, `core.rpc-manager`);
if ((_a = this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(INFO)) {
this._logger.info("setting up sub-systems.");
}
this.eventDistributor = new PubSubSystem();
this.dataDistributor = new DataPubSubSystem();
const defaultSelector = generateSelector(options.defaultSelector || "first", this);
// Creating the Connectivity Manager:
this.connectivityManager = new NopeConnectivityManager(options, generateObservable, this.id);
// Create our RPC-Manger.
this.rpcManager = new NopeRpcManager(options, generateObservable, defaultSelector, this.id, this.connectivityManager);
// Create our Instance Manager
this.instanceManager = new NopeInstanceManager(options, generateEmitter, generateObservable, defaultSelector, this.id, this.connectivityManager, this.rpcManager, this);
this.ready = generateObservable();
this.ready.getter = () => {
return (this.connectivityManager.ready.getContent() &&
this.rpcManager.ready.getContent() &&
this.instanceManager.ready.getContent());
};
const rcvExternally = generateId();
// 1. Subscribe to the events:
this.communicator.on("event", (msg) => {
if (msg.sender !== this.id) {
// split the Message in segments
const { path, data, ...options } = msg;
// Now, we know, that we have updated the data
// so, if there is an update, we will prevent this
// by setting the sender to the external id
options.sender = rcvExternally;
// Push the Data.
this.eventDistributor.emit(path, data, options);
}
});
this.eventDistributor.onIncrementalDataChange.subscribe((item) => {
if (item.sender !== rcvExternally) {
this.communicator.emit("event", {
...item,
sender: this.id,
});
}
});
// Link the Data-Distributor:
// 1. Subscribe to the changes:
this.communicator.on("dataChanged", (msg) => {
if (msg.sender !== this.id) {
// split the Message in segments
const { path: name, data, ...options } = msg;
// We will prevent to
options.sender = rcvExternally;
// Push the Data.
this.dataDistributor.pushData(name, data, options);
}
});
// 2. Enable emitting the updates
this.dataDistributor.onIncrementalDataChange.subscribe((item) => {
if (item.sender !== rcvExternally) {
this.communicator.emit("dataChanged", {
...item,
sender: this.id,
});
}
});
this.connectivityManager.ready.subscribe((_) => {
this.ready.forcePublish();
});
this.rpcManager.ready.subscribe((_) => {
this.ready.forcePublish();
});
this.instanceManager.ready.subscribe((_) => {
this.ready.forcePublish();
});
this.disposing = false;
registerGarbageCallback(this, this.dispose.bind(this));
}
// See interface description
async dispose() {
this.disposing = true;
await this.ready.dispose();
await this.eventDistributor.dispose();
await this.dataDistributor.dispose();
await this.connectivityManager.dispose();
await this.rpcManager.dispose();
await this.instanceManager.dispose();
}
toDescription() {
const ret = {
...this.connectivityManager.info,
ready: this.ready.getContent(),
bridge: this.options.communicator.toDescription(),
eventDistributor: this.eventDistributor.toDescription(),
dataDistributor: this.dataDistributor.toDescription(),
connectivityManager: this.connectivityManager.toDescription(),
rpcManager: this.rpcManager.toDescription(),
instanceManager: this.instanceManager.toDescription(),
};
return ret;
}
}