fix: prevent duplicate suno task refunds via cas status update (#6074)

* fix: prevent duplicate suno task refunds via cas status update

* fix: reconcile failed task refunds

---------

Co-authored-by: CaIon <i@caion.me>
This commit is contained in:
feitianbubu
2026-07-20 22:03:13 +08:00
committed by GitHub
co-authored by CaIon
parent 4aa08f917e
commit e0d5156115
7 changed files with 456 additions and 16 deletions
+12 -3
View File
@@ -162,16 +162,17 @@ func taskModelName(task *model.Task) string {
// RefundTaskQuota 统一的任务失败退款逻辑。
// 当异步任务失败时,将预扣的 quota 退还给用户(支持钱包和订阅),并退还令牌额度。
func RefundTaskQuota(ctx context.Context, task *model.Task, reason string) {
// 返回资金来源是否已成功退还;失败时保留 quota 作为后续对账标记。
func RefundTaskQuota(ctx context.Context, task *model.Task, reason string) bool {
quota := task.Quota
if quota == 0 {
return
return true
}
// 1. 退还资金来源(钱包或订阅)
if err := taskAdjustFunding(task, -quota); err != nil {
logger.LogWarn(ctx, fmt.Sprintf("退还资金来源失败 task %s: %s", task.TaskID, err.Error()))
return
return false
}
// 2. 退还令牌额度
@@ -192,6 +193,14 @@ func RefundTaskQuota(ctx context.Context, task *model.Task, reason string) {
Group: task.Group,
Other: other,
})
// 4. 资金退款完成后再清除持久化标记;失败时保留非零 quota,
// 由后续对账重试。回写失败必须显式告警,避免漏掉潜在的重复退款风险。
task.Quota = 0
if err := task.UpdateQuota(); err != nil {
logger.LogError(ctx, fmt.Sprintf("退款成功但清除 task quota 失败 task %s: %s", task.TaskID, err.Error()))
}
return true
}
// RecalculateTaskQuota 通用的异步差额结算。