UNPKG

@hotmeshio/hotmesh

Version:

Serverless Workflow

98 lines (97 loc) 4.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getProxyInterruptPayload = exports.wrapActivity = exports.proxyActivities = void 0; const common_1 = require("./common"); const context_1 = require("./context"); const didRun_1 = require("./didRun"); /** * Constructs payload for spawning a proxyActivity job. * @private */ function getProxyInterruptPayload(context, activityName, execIndex, args, options) { const { workflowDimension, workflowId, originJobId, workflowTopic, expire } = context; const activityTopic = `${workflowTopic}-activity`; const activityJobId = `-${workflowId}-$${activityName}${workflowDimension}-${execIndex}`; let maximumInterval; if (options?.retryPolicy?.maximumInterval) { maximumInterval = (0, common_1.s)(options.retryPolicy.maximumInterval); } return { arguments: args, workflowDimension, index: execIndex, originJobId: originJobId || workflowId, parentWorkflowId: workflowId, workflowId: activityJobId, workflowTopic: activityTopic, activityName, expire: options?.expire ?? expire, backoffCoefficient: options?.retryPolicy?.backoffCoefficient ?? undefined, maximumAttempts: options?.retryPolicy?.maximumAttempts ?? undefined, maximumInterval: maximumInterval ?? undefined, }; } exports.getProxyInterruptPayload = getProxyInterruptPayload; /** * Wraps a single activity in a proxy, orchestrating its execution and replay. * @private */ function wrapActivity(activityName, options) { return async function (...args) { const [didRunAlready, execIndex, result] = await (0, didRun_1.didRun)('proxy'); if (didRunAlready) { if (result?.$error) { if (options?.retryPolicy?.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 { // Non-fatal error } } return result.$error; } return result.data; } const context = (0, context_1.getContext)(); const { interruptionRegistry } = context; const interruptionMessage = getProxyInterruptPayload(context, activityName, execIndex, args, options); interruptionRegistry.push({ code: common_1.HMSH_CODE_MESHFLOW_PROXY, ...interruptionMessage, }); await (0, common_1.sleepImmediate)(); throw new common_1.MeshFlowProxyError(interruptionMessage); }; } exports.wrapActivity = wrapActivity; /** * Provides a proxy for defined activities, ensuring deterministic replay and retry. * @template ACT * @param {ActivityConfig} [options] - Optional activity config (includes retryPolicy). * @returns {ProxyType<ACT>} A proxy to call activities as if local, but durably managed by the workflow. */ function proxyActivities(options) { if (options?.activities) { common_1.WorkerService.registerActivities(options.activities); } const proxy = {}; const keys = Object.keys(common_1.WorkerService.activityRegistry); if (keys.length) { keys.forEach((key) => { const activityFunction = common_1.WorkerService.activityRegistry[key]; proxy[key] = wrapActivity(key, options); }); } return proxy; } exports.proxyActivities = proxyActivities;