---
schema: "hl-changelog/v2"
ticket: "5588"
title: "司机/车辆占用缓存态对账任务（修正脏busy并释放过期holding占用）"
consumer: "admin"
author: "wx(GIT)"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "后端完成：PR #5591 已合并 dev-v3 并部署 TEST，网关验证 3/3 通过。新增 internal 对账端点（Quartz 触发），无前端 API 变化。"
updated_at: "2026-08-06"
base: "dev-v3"
generated: "2026-08-06T13:10:00+08:00"
---

# 司机/车辆占用缓存态对账任务（修正脏busy并释放过期holding占用）

> 后端完成：PR #5591 已合并 dev-v3 并部署 TEST，网关验证 3/3 通过。

## 关联 / 联系人

### 链接

- **Issue**: [#5588](https://git.1814.love:8443/wx/HL/issues/5588)
- **PR**: [#5591](https://git.1814.love:8443/wx/HL/pulls/5591)
- **Merge commit**: [deecd62b3](https://git.1814.love:8443/wx/HL/commit/deecd62b3)

### 联系人

- **后端负责人**: @wx

## 背景

协调台 E2E 实证：派单发送被"尚未通过候选校验"拦截，根因是 driver_status/vehicle_status 未释放回 idle——**16 个 busy 司机中 6 个无 active 占用（37%），车辆同样**，可派资源被大面积误锁。

代码链路核对结论：取消派单释放占用的既有链路（publishCanceledEvents → OCCUPANCY_RECOMPUTE outbox → hasActiveAssignmentBy* 反算 → applyOccupancy 守卫）已覆盖全部取消入口。TEST 库脏 busy 实际根因：
1. **5 个司机从未有派单却 busy**（外部批量写入缓存列，无事件链路可修复）
2. **holding 单服务日自然过期后无事件触发反算**（如乌力吉/蒙C04E04：08-03~05 holding 单 08-05 结束后占用永久残留）——`AssignmentCompleteJob` 只完结 assigned，不处理过期 holding

## 变更接口

| 方法 | 路径 | 来源 | 说明 |
|---|---|---|---|
| `POST` | `/internal/fleet/jobs/occupancy-reconcile/run` | `FleetJobInternalController`（fleet） | **新增** internal 端点，由 hl-user-service Quartz（sys_job）单点触发；返回本轮写入的 OCCUPANCY_RECOMPUTE 意图数 |

`/internal/*` 经 InternalAuthInterceptor 校验 X-Internal-Token，走内网 Feign LB 直连不经网关（admin token 直 curl 403 属正常）。**无前端 API 变化**。

## 行为变化

新增 `OccupancyReconcileJob`（占用缓存态对账）：
- **对账口径**：以 active 派单（holding/assigned 且 end_date >= today）为唯一真相；busy 但无 active 占用的司机/车辆为脏态
- **执行方式**：扫 busy 司机/车辆 + 过期 holding 行资源，逐一写 OCCUPANCY_RECOMPUTE 意图（Outbox），由既有处理器在资源锁内反算并按守卫写回 busy/idle
- **安全性**：不改派单行、不直接改缓存列、不绕过业务守卫（rest/pending/maint 人工态不被覆盖）；幂等（无 active 占用才回 idle）；单资源失败不反噬整轮
- **附带修复**：过期 holding（服务日已过但从未产生事件）行资源的占用一并释放

## 前端/调用方动作

无。对账由 sys_job 定时触发（建议每日一次），无需前端配合。

## 验证证据

- 定向测试：OccupancyReconcileJobTest 4/4；AssignmentServiceTest 372、AssignmentCandidateServiceTest 45 全过
- fleet verify **3184 项**（含 MySQL 8.0.33 集成）0 失败；spotless 通过
- 网关验证（TEST，12:58）：对账前脏 busy 司机=6 车辆=5；触发对账端点（32 条 recompute 意图全 SUCCESS）；对账后脏 busy **归零**（原 6 司机 5 车辆全部 idle）；候选复验朝鲁门（有 active 占用）仍 busy + available=false（ASSIGNMENT_CONFLICT），**未被误释放**
