@hotmeshio/hotmesh
Version:
Serverless Workflow
98 lines (97 loc) • 4.07 kB
JavaScript
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;
;