chrono-forge
Version:
A comprehensive framework for building resilient Temporal workflows, advanced state management, and real-time streaming activities in TypeScript. Designed for a seamless developer experience with powerful abstractions, dynamic orchestration, and full cont
81 lines (80 loc) • 3.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Step = void 0;
require("reflect-metadata");
const metadata_1 = require("./metadata");
const Step = (options = {}) => {
return (target, propertyKey, descriptor) => {
const stepName = options.name ?? propertyKey;
const originalMethod = descriptor.value;
descriptor.value = async function (...args) {
const steps = Reflect.getMetadata(metadata_1.STEP_METADATA_KEY, target) || [];
const stepMetadata = steps.find((s) => s.name === stepName);
try {
let result;
let attempts = 0;
const maxAttempts = (stepMetadata?.retries || 0) + 1;
while (attempts < maxAttempts) {
attempts++;
try {
if (stepMetadata?.timeout) {
const timeoutPromise = new Promise((_, reject) => {
const timeoutId = setTimeout(() => reject(new Error(`Step '${stepName}' timed out after ${stepMetadata.timeout}ms`)), stepMetadata.timeout);
return () => clearTimeout(timeoutId);
});
result = await Promise.race([originalMethod.apply(this, args), timeoutPromise]);
}
else {
result = await originalMethod.apply(this, args);
}
break;
}
catch (error) {
if (attempts >= maxAttempts) {
throw error;
}
const errorMessage = error instanceof Error ? error.message : String(error);
this.log?.warn?.(`Step '${stepName}' failed, retrying (${attempts}/${maxAttempts}): ${errorMessage}`);
}
}
if (stepMetadata) {
stepMetadata.executed = true;
stepMetadata.result = result;
}
return result;
}
catch (error) {
if (stepMetadata?.onError) {
try {
const handledResult = stepMetadata.onError(error instanceof Error ? error : new Error(String(error)));
stepMetadata.executed = true;
stepMetadata.result = handledResult;
return handledResult;
}
catch (handlerError) {
error = handlerError;
}
}
const errorMessage = error instanceof Error ? error.message : String(error);
this.log?.error?.(`Step '${stepName}' failed: ${errorMessage}`);
throw error;
}
};
const steps = Reflect.getMetadata(metadata_1.STEP_METADATA_KEY, target) || [];
steps.push({
name: stepName,
method: propertyKey,
on: options.on,
before: options.before,
after: options.after,
retries: options.retries || 0,
timeout: options.timeout,
required: options.required !== false,
onError: options.onError,
executed: false
});
Reflect.defineMetadata(metadata_1.STEP_METADATA_KEY, steps, target);
return descriptor;
};
};
exports.Step = Step;