@hotmeshio/hotmesh
Version:
Serverless Workflow
103 lines (102 loc) • 4.18 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.startChild = exports.executeChild = exports.execChild = void 0;
const common_1 = require("./common");
const context_1 = require("./context");
const didRun_1 = require("./didRun");
/**
* Constructs the payload necessary to spawn a child workflow.
* @private
*/
function getChildInterruptPayload(context, options, execIndex) {
const { workflowId, originJobId, workflowDimension, expire } = context;
let childJobId;
if (options.workflowId) {
childJobId = options.workflowId;
}
else if (options.entity) {
childJobId = `${options.entity}-${(0, common_1.guid)()}-${workflowDimension}-${execIndex}`;
}
else {
childJobId = `-${options.workflowName}-${(0, common_1.guid)()}-${workflowDimension}-${execIndex}`;
}
const parentWorkflowId = workflowId;
const taskQueueName = options.taskQueue ?? options.entity;
const workflowName = options.entity ?? options.workflowName;
const workflowTopic = `${taskQueueName}-${workflowName}`;
return {
arguments: [...(options.args || [])],
await: options?.await ?? true,
backoffCoefficient: options?.config?.backoffCoefficient ?? common_1.HMSH_MESHFLOW_EXP_BACKOFF,
index: execIndex,
maximumAttempts: options?.config?.maximumAttempts ?? common_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
maximumInterval: (0, common_1.s)(options?.config?.maximumInterval ?? common_1.HMSH_MESHFLOW_MAX_INTERVAL),
originJobId: originJobId ?? workflowId,
expire: options.expire ?? expire,
persistent: options.persistent,
signalIn: options.signalIn,
parentWorkflowId,
workflowDimension: workflowDimension,
workflowId: childJobId,
workflowTopic,
};
}
/**
* Spawns a child workflow and awaits the result, or if `await` is false, returns immediately.
* @template T
* @param {WorkflowOptions} options - Workflow options.
* @returns {Promise<T>} Result of the child workflow.
*/
async function execChild(options) {
const isStartChild = options.await === false;
const prefix = isStartChild ? 'start' : 'child';
const [didRunAlready, execIndex, result] = await (0, didRun_1.didRun)(prefix);
const context = (0, context_1.getContext)();
const { canRetry, interruptionRegistry } = context;
if (didRunAlready) {
if (result?.$error && (!result.$error.is_stream_error || !canRetry)) {
if (options?.config?.throwOnError !== false) {
const code = result.$error.code;
const message = result.$error.message;
const stack = result.$error.stack;
if (code === common_1.HMSH_CODE_MESHFLOW_FATAL) {
throw new common_1.MeshFlowFatalError(message, stack);
}
else if (code === common_1.HMSH_CODE_MESHFLOW_MAXED) {
throw new common_1.MeshFlowMaxedError(message, stack);
}
else if (code === common_1.HMSH_CODE_MESHFLOW_TIMEOUT) {
throw new common_1.MeshFlowTimeoutError(message, stack);
}
else {
throw new common_1.MeshFlowRetryError(message, stack);
}
}
return result.$error;
}
else if (!result?.$error) {
return result.data;
}
}
const interruptionMessage = getChildInterruptPayload(context, options, execIndex);
interruptionRegistry.push({
code: common_1.HMSH_CODE_MESHFLOW_CHILD,
...interruptionMessage,
});
await (0, common_1.sleepImmediate)();
throw new common_1.MeshFlowChildError(interruptionMessage);
}
exports.execChild = execChild;
/**
* Alias for execChild.
*/
exports.executeChild = execChild;
/**
* Spawns a child workflow and returns the child Job ID without awaiting its completion.
* @param {WorkflowOptions} options - Workflow options.
* @returns {Promise<string>} The child job ID.
*/
async function startChild(options) {
return execChild({ ...options, await: false });
}
exports.startChild = startChild;
;