|
|
@@ -733,19 +733,26 @@ class Worker {
|
|
|
} catch (err) {
|
|
|
this.logger.error(`[${traceId}] 乐跑流程失败:`, err)
|
|
|
|
|
|
- // 非阻塞:非常见错误时通知管理员(过滤:当天已跑/不在时间/登录过期)
|
|
|
- Promise.resolve().then(async () => {
|
|
|
- try {
|
|
|
- await this.notifyAdminsUncommonLepaoError({
|
|
|
- account: req?.account,
|
|
|
- name: userData?.name,
|
|
|
- traceId,
|
|
|
- taskType: 'lepao.startRun',
|
|
|
- reason: err?.message || '未知错误',
|
|
|
- code: err?.code
|
|
|
- })
|
|
|
- } catch (_) { }
|
|
|
- })
|
|
|
+ const retryNow = Number(ctx?.retry || 0)
|
|
|
+ const maxRetry = Number(ctx?.maxRetry ?? this.maxRetry)
|
|
|
+ const canRetry = this.isRetryableTaskError(err) && retryNow < maxRetry
|
|
|
+ const isFinalAttemptFail = !canRetry
|
|
|
+
|
|
|
+ // 仅在所有重试均失败后才发异常告警/失败通知,避免每次重试都打扰
|
|
|
+ if (isFinalAttemptFail) {
|
|
|
+ Promise.resolve().then(async () => {
|
|
|
+ try {
|
|
|
+ await this.notifyAdminsUncommonLepaoError({
|
|
|
+ account: req?.account,
|
|
|
+ name: userData?.name,
|
|
|
+ traceId,
|
|
|
+ taskType: 'lepao.startRun',
|
|
|
+ reason: err?.message || '未知错误',
|
|
|
+ code: err?.code
|
|
|
+ })
|
|
|
+ } catch (_) { }
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
// 若已扣减次数,则失败时返还(幂等)
|
|
|
try {
|
|
|
@@ -757,7 +764,7 @@ class Worker {
|
|
|
this.logger.error(`[${traceId}] 返还乐跑次数失败:${e.stack || e}`)
|
|
|
}
|
|
|
|
|
|
- if (ctx.channel) {
|
|
|
+ if (ctx.channel && isFinalAttemptFail) {
|
|
|
await this.enqueueTask(ctx.channel, 'lepao.sendNotice', {
|
|
|
account: req.account,
|
|
|
success: false,
|
|
|
@@ -1446,7 +1453,14 @@ class Worker {
|
|
|
const proxyEnabled = await QgProxyManager.isOutboundProxyEnabled()
|
|
|
const outboundMode = proxyEnabled ? 'proxy' : 'direct'
|
|
|
const result = await this.withTimeout(
|
|
|
- handler(data, { traceId, channel, taskId: id, outboundMode }),
|
|
|
+ handler(data, {
|
|
|
+ traceId,
|
|
|
+ channel,
|
|
|
+ taskId: id,
|
|
|
+ outboundMode,
|
|
|
+ retry,
|
|
|
+ maxRetry: this.maxRetry
|
|
|
+ }),
|
|
|
type,
|
|
|
this.taskTimeoutMs,
|
|
|
{ code: 'TASK_TIMEOUT', retryable: true }
|