Skip to content

Commit cc4801d

Browse files
rootclaude
authored andcommitted
fix: enhance network error retry mechanism for polling
Expand retryable error codes in request and polling logic to improve resilience in unstable network environments. - Add support for ECONNRESET, ENOTFOUND, ECONNREFUSED, EAI_AGAIN, EPIPE, ENETUNREACH, EHOSTUNREACH error codes - Add 'socket hang up' error message detection - Implement retry logic in SmartPoller to continue polling on transient network errors instead of aborting immediately Closes #118 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d0f840b commit cc4801d

2 files changed

Lines changed: 33 additions & 4 deletions

File tree

src/api/controllers/core.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,19 @@ export async function request(
386386
logger.error(`请求失败 (尝试 ${retries + 1}/${maxRetries + 1}): ${error.message}`);
387387

388388
// 如果是网络错误或超时,尝试重试
389-
if ((error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' ||
390-
error.message.includes('timeout') || error.message.includes('network')) &&
391-
retries < maxRetries) {
389+
// 包含常见的网络错误:ECONNRESET(连接重置)、ENOTFOUND(DNS解析失败)、
390+
// ECONNREFUSED(连接被拒绝)、EAI_AGAIN(DNS临时失败)、EPIPE(管道破裂)
391+
const retryableErrorCodes = [
392+
'ECONNABORTED', 'ETIMEDOUT', 'ECONNRESET', 'ENOTFOUND',
393+
'ECONNREFUSED', 'EAI_AGAIN', 'EPIPE', 'ENETUNREACH', 'EHOSTUNREACH'
394+
];
395+
const isRetryableError = retryableErrorCodes.includes(error.code) ||
396+
error.message.includes('timeout') ||
397+
error.message.includes('network') ||
398+
error.message.includes('ECONNRESET') ||
399+
error.message.includes('socket hang up');
400+
401+
if (isRetryableError && retries < maxRetries) {
392402
retries++;
393403
continue;
394404
}

src/lib/smart-poller.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,26 @@ export class SmartPoller {
218218
}
219219

220220
} catch (error) {
221-
logger.error(`轮询过程中发生错误: ${error.message}`);
221+
// 判断是否为可重试的网络错误
222+
const retryableErrorCodes = [
223+
'ECONNABORTED', 'ETIMEDOUT', 'ECONNRESET', 'ENOTFOUND',
224+
'ECONNREFUSED', 'EAI_AGAIN', 'EPIPE', 'ENETUNREACH', 'EHOSTUNREACH'
225+
];
226+
const isRetryableError = retryableErrorCodes.includes(error.code) ||
227+
error.message?.includes('timeout') ||
228+
error.message?.includes('network') ||
229+
error.message?.includes('ECONNRESET') ||
230+
error.message?.includes('socket hang up');
231+
232+
// 网络错误时进行轮询级别的重试,而不是直接中断整个流程
233+
if (isRetryableError && this.pollCount < this.options.maxPollCount) {
234+
logger.warn(`轮询过程中发生网络错误 (${error.code || error.message}),等待后继续轮询...`);
235+
await new Promise(resolve => setTimeout(resolve, this.options.pollInterval));
236+
continue;
237+
}
238+
239+
// 不可重试的错误或已达到最大轮询次数,抛出异常
240+
logger.error(`轮询过程中发生不可恢复的错误: ${error.message}`);
222241
throw error;
223242
}
224243
}

0 commit comments

Comments
 (0)