#8002:605008 语义收窄为「等待窗口内没抢到」专用,持锁期内复核/续租发现锁已
丢的 4 处改抛 605075(带 {0} 锁身份标签)。前端不能再把两者都按「系统繁忙,
稍后重试」处理——605075 重试无效且意味着可能已有并发写入。
#8064:接口契约零变化,变的是同一请求的副作用。共用关系的成员因真实释放路径
失去占用时会被自动移出,剩余不足 2 人时关系自动解除。这两件事在修复前于当前
部署形态(占用账本 LEGACY)下一次都没发生过——全库 release_reason=
AUTO_SINGLE_MEMBER 计数由 0 变 1 是它的硬判据。
两份都按 origin/dev-v3=c1a6e96c8 逐条复核过行号与文案;#8002 那份订正了自动
生成稿里的 5 处事实错误,订正记录连同旧值一起留在文件里。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
11 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 8064 | fleet: 共用关系成员失去占用后,关系现在会自动收缩(行为变更,无接口契约变化) | admin | wx(GIT) | 修复 | deployed | verified | pending | 2026-09-21 | 本条无任何接口出入参或错误码变化,变的是同一请求的副作用:共用关系现在会在成员失去占用时自动收缩、剩余不足 2 人时自动解除。gateway_status=verified 的依据是 2026-09-21 经网关 https://api.test.1814.love:9443 的真实调用(建关系 + 两次 soft-clear-assignment),调用流水与库内终态逐条对照一致,不是只看部署登记。frontend_status 取 pending 而非 not_required:本条会让共用关系『自己消失』,前端是否需要改代码取决于它有没有缓存 activeShareGroupId 或假设关系只能人工解除——那是我无法从后端查证的事实,所以不替前端下 not_required 的结论;mmg 评估后若确认零改动,再由前端侧改为 not_required。⚠️ 存量数据尚未收敛(工单 #8064 AC-5 未完成,成文时实测孤儿关系 7 条),本次修复只对修复上线后发生的释放动作生效。 | 2026-09-21 | dev-v3 |
fleet: 共用关系成员失去占用后,关系现在会自动收缩(行为变更,无接口契约变化)
存放目录: 二期(fleet 车务)→
changelogs-v2/2026-09/
⚠️ 关键变化
接口契约零变化——没有新增/修改/删除任何端点,没有新增/修改任何请求或响应字段,没有新增任何错误码。
变的是同一个请求的副作用。 从本次修复上线起:
- 共用关系的某个成员因任何一条真实的占用释放路径失去对该车/该司机的占用时,该成员会被自动移出关系(成员行落
left_at,leave_reason = AUTO_OCCUPANCY_RELEASE); - 移出后剩余成员不足 2 个时,整条关系自动解除(
status = RELEASED,release_reason = AUTO_SINGLE_MEMBER,active_share_group_id置空)。
🔴 这两件事在本次修复之前,在当前部署形态下一次都没有发生过(不是"偶尔没触发",是整条代码路径执行不到,见"一、背景")。所以对前端而言,这是一个从未出现过的新现象,不是一个已有现象的修正。
一、背景
缺陷形态
自动收缩的唯一入口是 GroupDispatchShareOccupancyRefService.onClaimReleased(...),全仓唯一调用点在 OccupancyDualWriteCoordinator.notifyShareGroupOfRelease(...);后者只在 releaseCurrent(...) 内被调,releaseCurrent 只在 synchronizeOne(...) 内被调,而 synchronize() 的第一条语句是:
if (!context.dualWrite()) {
return;
}
而占用账本的灰度形态(fleet_occupancy_rollout_fence,64 条分片)在测试环境与生产环境全部为 LEGACY,并已于工单 #7972 定案维持不切(理由:回填完成前切换会让新账本少记占用,属于"用一个偏松的判据替掉现状")。
⇒ 在 LEGACY 形态下,synchronizeOne / releaseCurrent / notifyShareGroupOfRelease / onClaimReleased 整条链路一行都执行不到。
这个判断是怎么坐实的
不是靠读代码推断,是靠一个在"修好了"和"没修"两个世界里取值不同的读数:
| 读数 | 修复前 | 修复后 |
|---|---|---|
全库 fleet_group_dispatch_share_group.release_reason = 'AUTO_SINGLE_MEMBER' 计数 |
0 | 1 |
全库 fleet_group_dispatch_share_log 中 reason = 'AUTO_SINGLE_MEMBER' |
无 | 有 |
⚠️ 一个容易读错的邻近读数(写在这里免得下一个人重复踩):成员行的 leave_reason = 'AUTO_OCCUPANCY_RELEASE' 修复前并不是 0,而是 28——但那 28 条全部来自手工解除路径(24 条属 MANUAL、4 条属 CLEAR_ALL),因为手工解除与自动收缩复用了同一个成员级原因值。⇒ 按成员行的 leave_reason 计数衡量自动收缩活跃度会错 86%,必须 join 到所属关系的 release_reason 才能分辨。
修复
- PR #8073(
c07942035):把 LEGACY 形态下的收缩动作挂到dualWrite闸门之前,使其在不切换账本形态的前提下真正执行。 - PR #8077(
3a92cafbf):整团解除时,审计用的关系解除原因不被自动收缩夺走(走豁免,而不是调整执行顺序)——即"整团解除"仍记为整团解除,不会被改写成AUTO_SINGLE_MEMBER。
二、变更接口清单(无)
本条不新增、不修改、不删除任何 HTTP 接口,也不改动任何请求/响应字段与错误码。
下列既有端点的行为副作用受影响(契约不变):
| METHOD | Path | 变化 |
|---|---|---|
| POST | /admin/fleet/assignments/{assignmentId}/soft-clear-assignment |
若该派单是某 active 共用关系的成员,调用后该成员被自动移出;剩余 < 2 人时关系自动解除 |
| POST | /admin/fleet/assignments/{assignmentId}/driver-reject |
同上 |
| POST | /admin/fleet/assignments/{assignmentId}/change(改派替换) |
同上 |
| POST | /admin/fleet/assignments/{assignmentId}/complete(完结) |
同上 |
| DELETE | /admin/fleet/assignments/{assignmentId}(取消) |
仅当被取消的行在取消前处于 unassigned 时才进入释放集,见下方"三、边界行为" |
三、边界行为(这一节比上面的清单更重要)
⛔ 取消派单通常不会触发收缩
DELETE /admin/fleet/assignments/{assignmentId} 对在途的派车行落的是 exception 而不是 canceled,而按工单 #6152 的定案,exception 保留占用。只有"取消前已是 unassigned"的那部分行会落 canceled 并进入释放集。
⇒ 前端不要把"取消派单"当成"会解除共用关系"的动作。 车务若想解除关系,正确动作是显式调解除接口,或使用软清。
会触发收缩的五条路径
软清 / 司机拒接 / 改派替换 / 完结 / 取消中落 canceled 的那一子集。它们在后端收敛到同一个写口,因此行为一致。
软清清的是整行,不是单一维度
软清会把该派车行的车与司机一起清空(车辆 id / 车牌 / 车型 / 司机 id / 姓名 / 电话全部置空,并把当日车辆用量归零)。⇒ 若该派单同时参与了 VEHICLE 维度与 DRIVER 维度的两条共用关系,两条都会受影响,不是只动一条。
整团解除不会被改写成自动收缩
整团解除时,关系的 release_reason 仍记录整团解除的原因,不会被自动收缩改写成 AUTO_SINGLE_MEMBER(PR #8077)。审计与对账按 release_reason 区分来源时,这一点是可靠的。
四、前端要做什么
需要确认的一件事:贵侧是否在任何地方缓存了共用关系状态(activeShareGroupId、关系成员列表、"该派单属于某共用关系"这一标志),或是否在代码/交互里假设了「共用关系只能由人工显式解除」。
- 若有 ⇒ 该假设已不再成立,关系会在上述释放类操作之后"自己消失",需要改为操作后重新拉取。
- 若无(每次都实时拉取)⇒ 前端零改动,请把
frontend_status改为not_required并说明依据。
⚠️ 我没有替贵侧填 not_required:那是一个关于前端代码的事实,后端查证不了。这个位由看得见前端代码的人来定。
五、测试环境已验证
部署:fleet 测试服部署点 51571c58a;git merge-base --is-ancestor c07942035 51571c58a 与 3a92cafbf 均为真;Nacos 两实例 healthy = true。
形态:fleet_occupancy_rollout_fence 维持 LEGACY(未改任何配置、未翻闸门——在 DUAL_WRITE 下绿不能证明本缺陷修好了,那正是它的藏身处)。
网关:全部调用经 https://api.test.1814.love:9443,调用流水逐条留档。
夹具:服务日 2026-12-20(全新,不复用存量),团车 + 司机 + 甲乙两户,VEHICLE 维度共用关系,3 个 alive 成员。
三次查询逐条对:
- 软清前:3 个成员全部 alive,关系
status = ACTIVE,关系日志仅一条CREATE; - 软清甲之后:关系仍
ACTIVE、release_reason为 null、active_share_group_id仍指向本关系;甲的成员行left_at = 2026-09-21 01:14:08、leave_reason = AUTO_OCCUPANCY_RELEASE,而团车行与乙的left_at仍为 null ⇒ 剩 2 行 alive。(团车行与乙没动,是排除"整条关系被一把清掉"的阳性对照。) - 软清乙(最后一人)之后:
status = RELEASED、release_reason = AUTO_SINGLE_MEMBER、active_share_group_id = NULL、released_at = 2026-09-21 01:14:08;关系日志出现{action: RELEASED, reason: AUTO_SINGLE_MEMBER}。
六、不影响范围
- 任何接口的请求参数、响应字段、错误码——一个都没动。
- 取消派单对在途行的行为(仍落
exception、仍保留占用,#6152 定案不变)。 - 整团解除的审计原因(PR #8077 专门保证它不被夺走)。
- 占用账本(
fleet_resource_occupancy_*)的灰度形态——仍维持LEGACY,本次修复没有切换它,这正是本次修复的设计目标:不靠切形态也能让收缩跑起来。 - 存量数据:⚠️ 未收敛。工单 #8064 AC-5 的存量收敛尚未执行(成文时实测孤儿关系 7 条,判据为"有 alive 成员但该成员已不占用本资源的 ACTIVE 关系")。本次修复只对修复上线之后发生的释放动作生效,历史遗留的不一致关系仍需单独收敛,完成后本文件会追加说明。
七、相关历史 PR
- PR #8073(
c07942035)—— 让自动收缩在 LEGACY 下真正执行。 - PR #8077(
3a92cafbf)—— 整团解除的审计原因不被自动收缩夺走。 - 工单 #7972 —— 定案占用账本形态维持
LEGACY不切(本缺陷得以长期存在的环境前提)。 - 工单 #6152 —— 取消派单对在途行落
exception且保留占用。 - 工单 #8061 —— 解除共用关系只清成员占用、同槽非成员不动。
关联 / 联系人
链接
- 后端工单:https://git.1814.love:8443/wx/HL/issues/8064
- PR:https://git.1814.love:8443/wx/HL/pulls/8073 、 https://git.1814.love:8443/wx/HL/pulls/8077
联系人
- 后端:wx
- 前端:mmg(本条需前端确认是否缓存了共用关系状态,见"四、前端要做什么")