修复(#11): 抽奖 Stage 2 Claim.ClaimData 空字符串违反 MySQL JSON 校验

Closes HIF-11 (Stage 2 P0)

F7 (P0): Claim.ClaimData=\"\" → MySQL error 3140 (Invalid JSON text: The document is empty)
- 修法:service.go:450 dispatchOrEnqueueClaim 构造 Claim 时显式 ClaimData=\"{}\"
- 完全同构 PR C PrizeSnapshot.Config / PR E UnmetReasons=\"[]\" / PR F Payload=\"{}\" 三处守卫

回归护栏:TestDraw_ManualClaimClaimDataIsValidJSON + claimDataIsValidJSON per-arg matcher(既拒 \"\" 也 json.Valid 校验)
Backend 反向自检:git stash fix 后测试立即抛 F7 regression 明确错误
CI 全绿;2 files, +116/-5;无 DB / API / flag 变更

架构师复盘:这是 code review 第 4 次漏检查同类 JSON 空串守卫(Stage 1 的 F4/F6 + Stage 2 的 F7)。感谢 QA 三次挖坑救场。Stage 3 起 code review 硬性 checklist 第一步:grep -RIn type:json sweep 全库。
This commit is contained in:
2026-07-12 19:09:54 -07:00
committed by GitHub
parent 07409eb602
commit 980e5adb90
2 changed files with 116 additions and 5 deletions
+7 -2
View File
@@ -452,8 +452,13 @@ func (s *Service) dispatchOrEnqueueClaim(ctx context.Context, tx *gorm.DB, req R
UserId: req.UserId,
ActivityId: req.ActivityId,
PrizeType: prize.Type,
Status: lottery.ClaimStatusPendingClaim,
ExpiresAt: expiresAt,
// ClaimData 是 JSON 列,MySQL 拒绝空字符串(error 3140)——用户填领奖
// 表单前用 "{}" 兜底,用户 POST /claim 会覆盖真实数据。与
// PrizeSnapshot.Config、EligibilitySnapshot.UnmetReasons、
// GrantLedger.Payload 的守卫风格一致。
ClaimData: "{}",
Status: lottery.ClaimStatusPendingClaim,
ExpiresAt: expiresAt,
}
if err := tx.WithContext(ctx).Create(&claim).Error; err != nil {
return lottery.DispatchResult{}, pendingClaimInfo{}, wrapInternal(fmt.Errorf("insert lottery_claim for draw %d: %w", draw.Id, err))