@openhps/core
Version:
Open Hybrid Positioning System - Core component
220 lines • 9.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkerBase = void 0;
const tslib_1 = require("tslib");
require("reflect-metadata");
const observable_1 = require("threads/observable");
const __1 = require(".."); // external @openhps/core
class WorkerBase {
constructor() {
this.pullOutput = new observable_1.Subject();
this.pushOutput = new observable_1.Subject();
this.serviceOutputCall = new observable_1.Subject();
this.serviceOutputResponse = new observable_1.Subject();
this.eventOutput = new observable_1.Subject();
this.customMethods = new Map();
}
setShape(shape) {
this.shape = shape;
}
init(config) {
return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
this.config = config;
const importFn = typeof process !== 'object'
? config.type === 'module'
? (file) => Promise.resolve(`${file}`).then(s => require(s)) // ES6
: (file) => Promise.resolve(importScripts(/* webpackIgnore: true */ file)) // CJS
: (file) => Promise.resolve(require(/* webpackIgnore: true */ file)); // eslint-disable-line
// Set global dir name
__dirname = config.directory; // eslint-disable-line
// Load external scripts
if (config.imports && config.imports.length > 0) {
config.imports.forEach((importFile) => {
importFn(importFile);
});
}
// Create model
const modelBuilder = __1.ModelBuilder.create();
// Add remote worker services if not already added
this.config.services.forEach((service) => {
if (service.dataType) {
const DataType = __1.DataSerializer.findTypeByName(service.dataType);
modelBuilder.addService(new __1.DummyDataService(service.uid, DataType), new __1.WorkerServiceProxy({
uid: service.uid,
callObservable: this.serviceOutputCall,
responseObservable: this.serviceOutputResponse,
}));
}
else {
modelBuilder.addService(new __1.DummyService(service.uid), new __1.WorkerServiceProxy({
uid: service.uid,
callObservable: this.serviceOutputCall,
responseObservable: this.serviceOutputResponse,
}));
}
});
this._initModel(modelBuilder);
// eslint-disable-next-line
const path = this.config.imports.length > 0 ? undefined : (typeof process !== 'object' ? undefined : require('path'));
try {
if (this.config.serialized) {
const traversalBuilder = modelBuilder.from();
const modelOrNode = __1.ModelSerializer.deserializeNode(this.config.serialized);
traversalBuilder.via(modelOrNode);
traversalBuilder.to();
}
else if (this.config.builder) {
const traversalBuilder = modelBuilder.from();
const builderCallback = eval(this.config.builder);
builderCallback(traversalBuilder, modelBuilder, this.config.args);
traversalBuilder.to();
}
else if (this.config.shape) {
const graph = yield importFn(path ? path.join(__dirname, this.config.shape) : this.config.shape);
if (graph) {
modelBuilder.addShape(graph.default);
}
}
else if (this.shape) {
modelBuilder.addShape(this.shape);
}
}
catch (ex) {
// Error deserializing, did you import the nodes?
reject(ex);
return;
}
modelBuilder
.build()
.then((m) => {
this.model = m;
// Load methods
this.config.methods.forEach((serializedMethod) => {
const method = eval(serializedMethod.handlerFn);
this.customMethods.set(serializedMethod.name, (model, ...args) => {
return Promise.resolve(method(model, ...args));
});
});
resolve();
})
.catch(reject);
}));
}
invokeMethod(methodName, ...args) {
return new Promise((resolve, reject) => {
const method = this.customMethods.get(methodName);
if (!method) {
return reject(new Error(`Unable to invoke unknown method '${methodName}'!`));
}
method(this.model, ...args.map((a) => __1.DataSerializer.deserialize(a)))
.then((result) => {
resolve(__1.DataSerializer.serialize(result));
})
.catch(reject);
});
}
/**
* Pull from this work
* @param {PullOptions} [options] Pull options
* @returns {Promise<void>} Pull promise
*/
pull(options) {
return this.model.pull(options);
}
/**
* Push to this worker
* @param {DataFrame} frame Data frame
* @param {PushOptions} [options] Push options
* @returns {Promise<void>} Push promise
*/
push(frame, options) {
return this.model.push(__1.DataSerializer.deserialize(frame), options);
}
/**
* Init the model internal input and internal output
* @param {ModelBuilder} modelBuilder Model builder
*/
_initModel(modelBuilder) {
const internalSource = new __1.CallbackSourceNode((options) => {
// Send a pull request to the main thread
this.pullOutput.next(options);
return undefined;
});
const internalSink = new __1.CallbackSinkNode((frame) => {
// Serialize the frame and transmit it to the main thread
this.pushOutput.next(__1.DataSerializer.serialize(frame));
});
modelBuilder.graph.deleteNode(modelBuilder.graph.internalSource);
modelBuilder.graph.internalSource = internalSource;
internalSource.on('error', (event) => {
this.eventOutput.next({
name: 'error',
event,
});
});
internalSource.on('completed', (event) => {
this.eventOutput.next({
name: 'completed',
event,
});
});
modelBuilder.graph.addNode(modelBuilder.graph.internalSource);
modelBuilder.graph.deleteNode(modelBuilder.graph.internalSink);
modelBuilder.graph.internalSink = internalSink;
modelBuilder.graph.addNode(modelBuilder.graph.internalSink);
}
findAllServices() {
return new Promise((resolve) => {
const services = this.model.findAllServices();
const servicesArray = services
.filter((service) => !(service instanceof __1.DummyDataService || service instanceof __1.DummyService))
.map((service) => {
// Services are wrapped in a proxy. Get prototype
const serviceBase = Object.getPrototypeOf(service);
return {
uid: service.uid,
type: serviceBase.constructor.name,
dataType: service instanceof __1.DataService ? service.driver.dataType.name : undefined,
};
});
resolve(servicesArray);
});
}
callService(call) {
return new Promise((resolve, reject) => {
const service = this.model.findDataService(call.serviceUID) || this.model.findService(call.serviceUID);
if (service[call.method]) {
const serializedParams = call.parameters;
const params = [];
serializedParams.forEach((param) => {
if (param['__type']) {
params.push(__1.DataSerializer.deserialize(param));
}
else {
params.push(param);
}
});
const promise = service[call.method](...params);
Promise.resolve(promise)
.then((_) => {
if (Array.isArray(_)) {
const result = [];
_.forEach((r) => {
result.push(__1.DataSerializer.serialize(r));
});
resolve({ id: call.id, success: true, result });
}
else {
const result = __1.DataSerializer.serialize(_);
resolve({ id: call.id, success: true, result });
}
})
.catch((ex) => {
reject({ id: call.id, success: false, result: ex });
});
}
});
}
}
exports.WorkerBase = WorkerBase;
//# sourceMappingURL=WorkerBase.js.map