|
@@ -629,7 +629,7 @@ class Worker {
|
|
|
run_end_time
|
|
run_end_time
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 1.5️⃣ 乐跑开始前扣减次数(失败会返还,且有幂等保护)
|
|
|
|
|
|
|
+ // 1.5️⃣ 乐跑开始前扣减次数(同一 MQ taskId 仅扣一次;仅当所有重试均失败后在 catch 中返还)
|
|
|
await this.handlers['lepao.consumeCount']({
|
|
await this.handlers['lepao.consumeCount']({
|
|
|
account: req.account,
|
|
account: req.account,
|
|
|
uuid: userData?.create_user
|
|
uuid: userData?.create_user
|
|
@@ -754,14 +754,16 @@ class Worker {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 若已扣减次数,则失败时返还(幂等)
|
|
|
|
|
- try {
|
|
|
|
|
- await this.handlers['lepao.refundCount']({
|
|
|
|
|
- account: req.account,
|
|
|
|
|
- uuid: userData?.create_user
|
|
|
|
|
- }, ctx)
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- this.logger.error(`[${traceId}] 返还乐跑次数失败:${e.stack || e}`)
|
|
|
|
|
|
|
+ // 仅终局失败(不可再 MQ 重试)时返还;中间重试保持已扣次数,避免重复扣/退抖动
|
|
|
|
|
+ if (isFinalAttemptFail) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await this.handlers['lepao.refundCount']({
|
|
|
|
|
+ account: req.account,
|
|
|
|
|
+ uuid: userData?.create_user
|
|
|
|
|
+ }, ctx)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.logger.error(`[${traceId}] 返还乐跑次数失败:${e.stack || e}`)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (ctx.channel && isFinalAttemptFail) {
|
|
if (ctx.channel && isFinalAttemptFail) {
|
|
@@ -900,7 +902,7 @@ class Worker {
|
|
|
throw new Error('扣减乐跑次数失败:缺少 uuid')
|
|
throw new Error('扣减乐跑次数失败:缺少 uuid')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 幂等:同一 taskId 只扣一次
|
|
|
|
|
|
|
+ // 幂等:同一 MQ taskId 全程(含多次重试投递)只扣一次;终局失败再一次性返还
|
|
|
const consumeKey = `lepao:consume:${ctx?.taskId || ctx?.traceId || account || uuid}`
|
|
const consumeKey = `lepao:consume:${ctx?.taskId || ctx?.traceId || account || uuid}`
|
|
|
const existed = await Redis.get(consumeKey)
|
|
const existed = await Redis.get(consumeKey)
|
|
|
if (existed) {
|
|
if (existed) {
|
|
@@ -961,7 +963,7 @@ class Worker {
|
|
|
return true
|
|
return true
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- /* ---------------- 返还次数(失败时执行) ---------------- */
|
|
|
|
|
|
|
+ /* ---------------- 返还次数(整次任务所有 MQ 重试耗尽后失败时执行) ---------------- */
|
|
|
this.register('lepao.refundCount', async (req, ctx) => {
|
|
this.register('lepao.refundCount', async (req, ctx) => {
|
|
|
const account = req?.account
|
|
const account = req?.account
|
|
|
const uuid = req?.uuid
|
|
const uuid = req?.uuid
|