@openhps/core
Version:
Open Hybrid Positioning System - Core component
179 lines • 5.42 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { v4 as uuidv4 } from 'uuid';
import { SerializableMember, SerializableObject } from '../../data/decorators';
import { AsyncEventEmitter } from '../../_internal/AsyncEventEmitter';
import { PushPromise } from '../PushPromise';
import { PullPromise } from '../PullPromise';
let GraphNode = class GraphNode extends AsyncEventEmitter {
constructor() {
super();
/**
* Unique identifier of node.
*/
this.uid = uuidv4();
this._ready = false;
this._available = true;
this.prependOnceListener('ready', () => {
this._ready = true;
});
this.on('error', this._onError.bind(this));
this.on('completed', this._onCompleted.bind(this));
}
get inletNode() {
return this;
}
get outletNode() {
return this;
}
/**
* Graph logger
* @param {string} level Logging level
* @param {string} message Message
* @param {any} data Data to include in log
*/
logger(level, message, data) {
if (typeof message === 'object') {
this.graph.logger(level, JSON.stringify(message));
} else {
this.graph.logger(level, message, data);
}
}
isReady() {
return this._ready;
}
/**
* Check if the node is available for accepting push requests
* @returns {boolean} Is the node available to push
*/
isAvailable() {
return this._available;
}
/**
* Get the outgoing edges
* @returns {Array<Outlet<DataFrame>>} Outgoing edges
*/
get outlets() {
return this.graph.edges.filter(edge => edge.inputNode.uid === this.uid);
}
/**
* Get the incoming edges
* @returns {Array<Inlet<DataFrame>>} Incoming edges
*/
get inlets() {
return this.graph.edges.filter(edge => edge.outputNode.uid === this.uid);
}
emit(name, ...args) {
if (name === 'ready') {
return super.emit('ready', this);
}
return super.emit(name, ...args);
}
on(name, listener) {
return super.on(name, listener);
}
once(name, listener) {
return super.once(name, listener);
}
/**
* Send a pull request to the node
* @param {PullOptions} [options] Pull options
* @returns {Promise<void>} Pull promise
*/
pull(options) {
return new PullPromise((resolve, reject) => {
const callbackPromises = [];
this.listeners('pull').forEach(callback => {
callbackPromises.push(callback(options));
});
if (callbackPromises.length === 0) {
this.inlets.forEach(inlet => {
callbackPromises.push(inlet.pull(options));
});
}
Promise.all(callbackPromises).then(() => {
resolve();
}).catch(reject);
});
}
/**
* Push data to the node
* @param {DataFrame | DataFrame[]} data Data frame to push
* @param {PushOptions} [options] Push options
* @returns {PushPromise<void>} Push promise
*/
push(data, options = {}) {
return new PushPromise((resolve, reject, completed) => {
if (data === null || data === undefined) {
return reject(new Error('Node received null data frame!'));
}
const listeners = this.listeners('push');
if (listeners.length === 0) {
// Forward push, resolve before outlets resolve
const pushPromises = this.outlets.map(outlet => outlet.push(data, options));
// Resolve
resolve();
Promise.all(pushPromises).then(() => {
completed();
}).catch(() => {
// Do nothing, promimse is already resolved
});
} else {
this._available = false;
Promise.all(listeners.map(callback => callback(data, options))).then(() => {
this._available = true;
this.emit('available');
resolve();
completed();
}).catch(reject);
}
});
}
/**
* Promise once the node is available
* @returns {Promise} Promise when the node is available
*/
onceAvailable() {
return new Promise(resolve => {
if (this.isAvailable()) {
resolve();
} else {
this.once('available', () => {
resolve();
});
}
});
}
/**
* Promise once the frame is completed
* @param {string} frameUID Frame UID
* @returns {Promise} Promise when the frame is completed
*/
onceCompleted(frameUID) {
return new Promise((resolve, reject) => {
const completedListener = function (event) {
if (event.frameUID === frameUID) {
this.removeListener('completed', completedListener);
this.removeListener('error', completedListener);
if (event.error) {
reject(event);
} else {
resolve(event);
}
}
};
this.on('completed', completedListener.bind(this));
this.on('error', completedListener.bind(this));
});
}
_onError(error) {
this.inlets.forEach(inlet => inlet.emit('error', error));
}
_onCompleted(event) {
this.logger('debug', `Node ${this.name} completed frame ${event.frameUID}`);
this.inlets.forEach(inlet => inlet.emit('completed', event));
}
};
__decorate([SerializableMember(), __metadata("design:type", String)], GraphNode.prototype, "name", void 0);
__decorate([SerializableMember(), __metadata("design:type", String)], GraphNode.prototype, "uid", void 0);
GraphNode = __decorate([SerializableObject(), __metadata("design:paramtypes", [])], GraphNode);
export { GraphNode };