@nazaire/orchestra
Version:
A framework for distributing work over many machines, integrated with Node.js workers to utilise many threads per machine.
106 lines • 3.32 kB
JavaScript
import { nanoid } from "nanoid";
import { MessageType } from "./Network/index.js";
import { NetworkClient } from "./Network/NetworkClient.js";
import { Transform } from "node:stream";
export class Client extends NetworkClient {
workspace;
constructor(network, workspace) {
super("client_" + nanoid(), network);
this.workspace = workspace;
}
/**
* Add a job to the composer's queue
* @param options
* @returns
*/
async queue(options) {
return await this.createJob(options);
}
/**
* Add a job and bypass the queue, returns the result once the job is complete
* @param options
* @returns the result of the job
*/
async play(options, onData) {
const job = await this.createJob(options, 1);
if (onData) {
const stream = await this.stream(job.id);
stream.on("data", onData);
}
return this.getJobResultPromise(job.id);
}
/**
* Return a promise that resolves with the job when it is complete
* @param jobId
* @returns
*/
async completion(jobId) {
return this.getJobCompletedPromise(jobId);
}
/**
* Return a promise that resolves with the result when the job is complete
*/
async result(jobId) {
return this.getJobResultPromise(jobId);
}
async stream(jobId) {
const stream = new Transform({
objectMode: true,
transform: (chunk, encoding, callback) => {
callback(null, chunk);
},
});
const subscription = await this.network.subscribeData((message) => {
if (message.type === MessageType.JOB_DATA && message.data.id === jobId) {
stream.write(message.data.data);
}
});
stream.on("close", () => {
subscription.unsubscribe();
});
this.getJobCompletedPromise(jobId).then(() => {
stream.end();
});
return stream;
}
/**
* Retrieve the current state of a job
* @param id
* @returns
*/
async getJob(id) {
const message = this.createMessage({
type: MessageType.QUERY_JOBS,
destination: "*",
data: { id },
});
const response = await this.sendAndAwaitResponse(message, 1000);
return response.data[0];
}
async createJob(options, priority = 0) {
const message = this.createMessage({
type: MessageType.CREATE_JOB,
destination: "composer",
data: { options, priority },
});
const response = await this.sendAndAwaitResponse(message, 1000);
return response.data;
}
async getJobCompletedPromise(jobId) {
const completedMessage = this.network.first((m) => m.type === MessageType.JOB_COMPLETED &&
m.data.id === jobId);
return completedMessage.then((value) => value.data);
}
getJobResultPromise(jobId) {
const completed = this.getJobCompletedPromise(jobId);
return completed.then((job) => {
if (job.error) {
throw new Error(job.error);
}
else {
return job.result;
}
});
}
}
//# sourceMappingURL=Client.js.map