chore(5336): change 端点 requestId 持久幂等交接(605059 与重放语义)
所有检测均成功
changelog-filename-gate / validate (push) Successful in 1s
所有检测均成功
changelog-filename-gate / validate (push) Successful in 1s
这个提交包含在:
父节点
118877e367
当前提交
c095a9d2fa
@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
schema: "hl-changelog/v2"
|
||||||
|
ticket: "5336"
|
||||||
|
title: "修改派单 requestId 持久幂等:同键重放冻结结果、不同载荷 605059"
|
||||||
|
consumer: "admin"
|
||||||
|
change_type: "修改接口"
|
||||||
|
backend_status: "deployed"
|
||||||
|
gateway_status: "verified"
|
||||||
|
frontend_status: "pending"
|
||||||
|
frontend_owner: ""
|
||||||
|
frontend_ref: ""
|
||||||
|
target_release: ""
|
||||||
|
verified_at: "2026-08-03"
|
||||||
|
status_note: "PR #5427 已 squash 合并到 dev-v3@d4243a2f6;测试部署任务 111419d8 双实例健康;网关真实 change 验证首次 200、同键同载荷重放冻结结果、同键异载荷 605059(前置 #5433 修复 clear 凭证 500 回归)。前端尚未领取,保持 pending。"
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
base: "dev-v3"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 修改派单 requestId 持久幂等:同键重放冻结结果、不同载荷 605059
|
||||||
|
|
||||||
|
> **服务**:`hl-fleet-service`
|
||||||
|
>
|
||||||
|
> **Issue**:[#5336](https://git.1814.love:8443/wx/HL/issues/5336)
|
||||||
|
>
|
||||||
|
> **影响范围**:管理后台「修改派单」接口的幂等语义与错误码
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 关键变化
|
||||||
|
|
||||||
|
- 以前:`change` 接口对 `requestId` 只有 Redis 10 秒快速防重;TTL 到期后**同一 requestId + 相同 payload 重放会再次执行改派**(取消旧切片、生成新 group/assignment ID 与生命周期副作用)。
|
||||||
|
- 现在:`(operationType=CHANGE, requestId)` 在数据库持久唯一;成功后同键同 payload 重放**直接返回首次冻结结果,不再产生任何改派副作用**;同键不同 payload 返回 `605059`。
|
||||||
|
- 前端/调用方以前以为的重放安全不再成立,**重试安全成为持久承诺**;任何新 `requestId` 的合法再次改派不受影响。
|
||||||
|
|
||||||
|
## 变更接口
|
||||||
|
|
||||||
|
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||||
|
|---|------|------|------|----------|------|
|
||||||
|
| 1 | 修改派单 | POST | `/admin/fleet/assignments/:assignmentId/change` | 错误码与幂等语义 | 无请求/响应字段变化 |
|
||||||
|
|
||||||
|
## 变更详情
|
||||||
|
|
||||||
|
### 3.1 幂等语义(行为变化)
|
||||||
|
|
||||||
|
- 请求体字段(含 `requestId`)与响应字段**均不变**。
|
||||||
|
- 首次成功后,相同 `requestId` + 相同业务载荷(规范化后)重放:返回首次冻结的完整响应(同 `assignmentId/assignmentSlotId/newAssignmentGroupId/...` 等),**不**生成新的 group/assignment、OperationLog、Outbox 或生命周期 intent。
|
||||||
|
- Redis 10 秒快速防重仍保留,仅承担首次并发抑制,不再承担业务正确性;DB 唯一回执跨 TTL 兜底。
|
||||||
|
- 同 `requestId` + 不同业务载荷:稳定失败,返回:
|
||||||
|
|
||||||
|
| code | 含义 |
|
||||||
|
|---|---|
|
||||||
|
| `605059` | 幂等请求标识已用于不同业务载荷 |
|
||||||
|
|
||||||
|
- `requestId` 大小写精确区分;首尾空白或超过 64 字符返回参数错误。
|
||||||
|
- 新 `requestId` 的再次合法改派不受阻,正常形成新业务变更。
|
||||||
|
|
||||||
|
## 前端消费动作
|
||||||
|
|
||||||
|
1. 正常业务无需改动;重试逻辑可依赖持久幂等(同键同载荷重复提交不再重复改派)。
|
||||||
|
2. 若收到 `605059`,说明同一 `requestId` 被用于不同内容,必须更换新 `requestId` 重新提交,不得原地重试。
|
||||||
|
3. 前端双击/重放场景:响应内容与首次一致,无需重新拉取详情。
|
||||||
|
|
||||||
|
## 验证证据
|
||||||
|
|
||||||
|
- Fleet H2 集成:`AssignmentChangeReceiptServiceIntegrationTest` 8/8、迁移测试 2/2。
|
||||||
|
- 真实 MySQL 8.0.33 + Redis + Spring AOP:`AssignmentChangeReceiptMysqlTest` 1/1(含跨 TTL 并发 exactly-once)。
|
||||||
|
- `AssignmentServiceTest` 340/340;Fleet 全量 verify 结果以 PR 合入后工单回写为准。
|
||||||
|
- oasdiff 与 Spring Cloud Contract 未配置,不能标记工具 PASS;以上为源码级字段对比与集成测试回退证据。
|
||||||
|
|
||||||
|
## Internal Feign / shared Java
|
||||||
|
|
||||||
|
无内部 Feign 或共享 Java 契约变化。
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户