You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
3.2 KiB
91 lines
3.2 KiB
|
4 months ago
|
import { __awaiter, __rest } from "tslib";
|
||
|
|
import EventEmitter from '@antv/event-emitter';
|
||
|
|
import { isFunction } from '@antv/util';
|
||
|
|
import * as Comlink from 'comlink';
|
||
|
|
/**
|
||
|
|
* @example
|
||
|
|
* const graph = new Graph();
|
||
|
|
* const layout = new CircularLayout();
|
||
|
|
*
|
||
|
|
* const supervisor = new Supervisor(graph, layout, { iterations: 1000 });
|
||
|
|
* const positions = await supervisor.execute();
|
||
|
|
* supervisor.stop();
|
||
|
|
* supervisor.kill();
|
||
|
|
*/
|
||
|
|
export class Supervisor extends EventEmitter {
|
||
|
|
constructor(graph, layout, options) {
|
||
|
|
super();
|
||
|
|
this.graph = graph;
|
||
|
|
this.layout = layout;
|
||
|
|
this.options = options;
|
||
|
|
this.spawnWorker();
|
||
|
|
}
|
||
|
|
spawnWorker() {
|
||
|
|
this.proxy = Comlink.wrap(
|
||
|
|
// @ts-ignore
|
||
|
|
new Worker(new URL('./worker.js', import.meta.url), { type: 'module' }));
|
||
|
|
if (this.running) {
|
||
|
|
this.running = false;
|
||
|
|
this.execute();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
execute() {
|
||
|
|
var _a;
|
||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
|
if (this.running)
|
||
|
|
return this;
|
||
|
|
this.running = true;
|
||
|
|
// Payload should include nodes & edges(if needed).
|
||
|
|
const _b = this.layout.options, { onTick } = _b, rest = __rest(_b, ["onTick"]);
|
||
|
|
const noFunctionOptions = {};
|
||
|
|
Object.keys(rest).forEach((name) => {
|
||
|
|
if (!isFunction(rest[name]))
|
||
|
|
noFunctionOptions[name] = rest[name];
|
||
|
|
});
|
||
|
|
const payload = {
|
||
|
|
layout: {
|
||
|
|
id: this.layout.id,
|
||
|
|
options: noFunctionOptions,
|
||
|
|
iterations: (_a = this.options) === null || _a === void 0 ? void 0 : _a.iterations,
|
||
|
|
},
|
||
|
|
nodes: this.graph.getAllNodes(),
|
||
|
|
edges: this.graph.getAllEdges(),
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* TODO: Convert graph object to linear memory(e.g. csr, adjacency matrix), then transfer the ownership to worker.
|
||
|
|
* @example
|
||
|
|
* const arraybufferWithNodesEdges = graphToByteArrays(this.graph); // Float32Array
|
||
|
|
*/
|
||
|
|
const arraybufferWithNodesEdges = new Float32Array([0]);
|
||
|
|
// TODO: Support transferables.
|
||
|
|
// @see https://www.npmjs.com/package/@naoak/workerize-transferable
|
||
|
|
// setupTransferableMethodsOnMain(this.worker, {
|
||
|
|
// calculateLayout: {
|
||
|
|
// // pick a transferable object from the method parameters
|
||
|
|
// pickTransferablesFromParams: (params) => [params[1].buffer],
|
||
|
|
// },
|
||
|
|
// });
|
||
|
|
const [positions] = yield this.proxy.calculateLayout(payload, [
|
||
|
|
arraybufferWithNodesEdges,
|
||
|
|
]);
|
||
|
|
return positions;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
stop() {
|
||
|
|
this.running = false;
|
||
|
|
// trigger `layout.stop()` if needed
|
||
|
|
this.proxy.stopLayout();
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
kill() {
|
||
|
|
// allow the GC to collect wrapper port
|
||
|
|
// @see https://github.com/GoogleChromeLabs/comlink#comlinkreleaseproxy
|
||
|
|
this.proxy[Comlink.releaseProxy]();
|
||
|
|
// TODO: unbind listeners on graph.
|
||
|
|
// TODO: release attached memory
|
||
|
|
}
|
||
|
|
isRunning() {
|
||
|
|
return this.running;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=supervisor.js.map
|