dasdasd
This commit is contained in:
parent
fafec7278d
commit
8ebb7779e0
@ -1,4 +1,5 @@
|
|||||||
const BaseAction = require('../core/base-action');
|
const BaseAction = require('../core/base-action');
|
||||||
|
const { ConfigurationError, TimeoutError } = require('../core/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义动作 - 调用适配器中的自定义函数
|
* 自定义动作 - 调用适配器中的自定义函数
|
||||||
@ -11,20 +12,30 @@ class CustomAction extends BaseAction {
|
|||||||
const timeout = this.config.timeout || 300000; // 默认5分钟超时
|
const timeout = this.config.timeout || 300000; // 默认5分钟超时
|
||||||
|
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
throw new Error('缺少处理函数名称');
|
throw new ConfigurationError('缺少处理函数名称', 'handler', {
|
||||||
|
action: 'custom',
|
||||||
|
config: this.config
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('info', `执行自定义函数: ${handler}`);
|
this.log('info', `执行自定义函数: ${handler}`);
|
||||||
|
|
||||||
// 检查适配器中是否存在该函数
|
// 检查适配器中是否存在该函数
|
||||||
if (typeof this.context.adapter[handler] !== 'function') {
|
if (typeof this.context.adapter[handler] !== 'function') {
|
||||||
throw new Error(`自定义处理函数不存在: ${handler}`);
|
throw new ConfigurationError(
|
||||||
|
`自定义处理函数不存在: ${handler}`,
|
||||||
|
`adapter.${handler}`,
|
||||||
|
{ availableHandlers: Object.keys(this.context.adapter) }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 Promise.race 实现超时保护
|
// 使用 Promise.race 实现超时保护
|
||||||
const timeoutPromise = new Promise((_, reject) => {
|
const timeoutPromise = new Promise((_, reject) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
reject(new Error(`自定义函数执行超时 (${timeout}ms): ${handler}`));
|
reject(new TimeoutError(`自定义函数: ${handler}`, timeout, {
|
||||||
|
handler,
|
||||||
|
params
|
||||||
|
}));
|
||||||
}, timeout);
|
}, timeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
const BaseAction = require('../core/base-action');
|
const BaseAction = require('../core/base-action');
|
||||||
|
const { ConfigurationError, TimeoutError, RetryExhaustedError } = require('../core/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重试块动作 - 将一组步骤作为整体进行重试
|
* 重试块动作 - 将一组步骤作为整体进行重试
|
||||||
|
* 支持整体超时保护,防止无限重试
|
||||||
*
|
*
|
||||||
* 配置示例:
|
* 配置示例:
|
||||||
* - action: retryBlock
|
* - action: retryBlock
|
||||||
* name: "支付流程"
|
* name: "支付流程"
|
||||||
* maxRetries: 5
|
* maxRetries: 5
|
||||||
* retryDelay: 2000
|
* retryDelay: 2000
|
||||||
|
* totalTimeout: 300000 # 整体超时5分钟
|
||||||
* onRetryBefore:
|
* onRetryBefore:
|
||||||
* - action: custom
|
* - action: custom
|
||||||
* handler: "regenerateCard"
|
* handler: "regenerateCard"
|
||||||
@ -23,6 +26,7 @@ class RetryBlockAction extends BaseAction {
|
|||||||
steps = [],
|
steps = [],
|
||||||
maxRetries = 3,
|
maxRetries = 3,
|
||||||
retryDelay = 1000,
|
retryDelay = 1000,
|
||||||
|
totalTimeout = 600000, // 默认10分钟整体超时
|
||||||
onRetryBefore = [],
|
onRetryBefore = [],
|
||||||
onRetryAfter = []
|
onRetryAfter = []
|
||||||
} = this.config;
|
} = this.config;
|
||||||
@ -30,12 +34,30 @@ class RetryBlockAction extends BaseAction {
|
|||||||
const blockName = this.config.name || 'RetryBlock';
|
const blockName = this.config.name || 'RetryBlock';
|
||||||
|
|
||||||
if (!steps || steps.length === 0) {
|
if (!steps || steps.length === 0) {
|
||||||
throw new Error('RetryBlock 必须包含至少一个步骤');
|
throw new ConfigurationError(
|
||||||
|
'RetryBlock 必须包含至少一个步骤',
|
||||||
|
'steps',
|
||||||
|
{ blockName, config: this.config }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastError = null;
|
let lastError = null;
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
||||||
|
// 检查整体超时
|
||||||
|
const elapsed = Date.now() - startTime;
|
||||||
|
if (elapsed > totalTimeout) {
|
||||||
|
throw new TimeoutError(
|
||||||
|
`${blockName} (整体)`,
|
||||||
|
totalTimeout,
|
||||||
|
{
|
||||||
|
attempts: attempt,
|
||||||
|
elapsed,
|
||||||
|
lastError: lastError?.message
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (attempt > 0) {
|
if (attempt > 0) {
|
||||||
this.log('info', `${blockName} - 第 ${attempt + 1} 次重试...`);
|
this.log('info', `${blockName} - 第 ${attempt + 1} 次重试...`);
|
||||||
@ -82,7 +104,15 @@ class RetryBlockAction extends BaseAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 所有重试都失败
|
// 所有重试都失败
|
||||||
throw new Error(`${blockName} 失败: ${lastError.message}`);
|
throw new RetryExhaustedError(
|
||||||
|
blockName,
|
||||||
|
maxRetries + 1,
|
||||||
|
{
|
||||||
|
lastError: lastError?.message,
|
||||||
|
stack: lastError?.stack,
|
||||||
|
totalTime: Date.now() - startTime
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user