Files
railwaysystem/docs/development/dms-r3/06_authorization_state_machine.md
T

137 lines
6.7 KiB
Markdown
Raw Normal View History

# 06 门锁授权与异步操作状态机设计 (Authorization State Machine)
> **语义铁律**:**DMS HTTP 200 `success: true` 仅代表“请求已保存/已受理 (REQUEST_ACCEPTED)”,绝不代表“门锁设备执行成功 (DEVICE_SUCCESS)”!**
> **门锁生效滞后性**:门锁作为电池供电的无线物联网终端,下发指令需要经过网关转发与微功耗空中唤醒,官方明确要求**调用成功 10 秒后再行查询操作状态**。
> **设计目标**:建立双层解耦状态机(业务授权状态 vs 设备操作状态),消除状态混淆。
---
## 1. 双层状态体系解耦定义
必须区分两个不同生命周期的状态机:
1. **门禁授权业务状态 (`DoorAuthorizationStatus`)**:站在学员与住宿业务视角,表达该住宿事实当前是否具备开门权限。
2. **外部硬件操作状态 (`ExternalOperationStatus`)**:站在异步任务与设备网络视角,表达向 DMS 派发的具体单次指令的执行进展。
---
## 2. 状态映射与状态定义字典
### 2.1 门禁授权业务状态 (`DoorAuthorizationStatus`)
| 本地业务状态枚举 | 业务含义 | 允许的操作 |
| :--- | :--- | :--- |
| **`UNISSUED`** (待下发) | 住宿已确认,尚未向门锁发起授权下发请求 | 下发授权 (`grant`) |
| **`ISSUING`** (下发中) | 已向 DMS 发送创建钥匙请求,已获得 `operationId`,正在等待 10 秒后对账确认 | 刷新状态、等待轮询 |
| **`ACTIVE`** (已生效/成功) | 轮询确认设备返回 `operationStatus = success`,学员可正常刷卡/输密码开门 | 查看凭据、撤销授权 (`revoke`) |
| **`ISSUE_FAILED`** (下发失败) | DMS 或设备明确返回失败,或超时重试达到上限 | 重新下发 (`retry`)、人工改派房间 |
| **`REVOKING`** (撤销中) | 学员退宿/调房,已向 DMS 提交删除钥匙请求,正在等待对账确认 | 刷新状态、等待轮询 |
| **`REVOKED`** (已注销) | 轮询确认钥匙已被设备成功删除,权限已彻底关闭 | 归档留存、不可逆 |
| **`EXPIRED`** (已到达有效期) | 超过 DMS 凭据设定的 `validUntil` 有效期边界(离线过期机制需供应商确认) | 自动归档、主动撤权兜底 |
### 2.2 外部硬件异步操作状态 (`ExternalOperationStatus`) 与 DMS 映射
| 本地操作状态枚举 | 对应 DMS API 原始字段 | 状态说明与处理策略 |
| :--- | :--- | :--- |
| **`CREATED`** | 内部构建指令,尚未发送 | 准备调用 HTTP 客户端 |
| **`REQUESTED`** | HTTP 请求发出,等待响应 | 网络传输中 |
| **`ACCEPTED`** | DMS 返回 `success: true`,携带 `operationId` | 记录 `operationId`,调度器挂起 10 秒轮询任务 |
| **`PENDING_DEVICE`** | 轮询返回 `operationStatus: "undone"` | 设备尚未完成执行,计算下次退避轮询时间 |
| **`SUCCESS`** | 轮询返回 `operationStatus: "success"` | 终态:设备已成功落锁/删除,触发推进业务状态 |
| **`FAILED`** | 轮询返回 `operationStatus: "failed"` | 终态:设备返回明确失败,记录 `resultDetails` 与错误原因 |
| **`TIMEOUT`** | 轮询返回 `operationStatus: "timeout"` | 终态:DMS 判定设备通信超时(10秒未响应),触发重试或报警 |
| **`RETRY_WAIT`** | 遭遇可恢复异常(如网络抖动),等待下一次重试 | 依据退避算法重新放入调度队列 |
---
## 3. 门锁授权端到端生命周期状态流转图 (Mermaid)
```mermaid
stateDiagram-v2
[*] --> UNISSUED : 住宿安排确认 (Accommodation Confirmed)
state "授权下发阶段 (Grant Flow)" as GrantFlow {
UNISSUED --> ISSUING : 触发下发 (报到或临近入住)
state ISSUING {
[*] --> Op_Requested : 调用 POST /online-password-key/create
Op_Requested --> Op_Accepted : DMS 返回 200 (获得 operationId)
Op_Accepted --> Op_Polling : 延迟等待 10 秒
Op_Polling --> Op_Undone : 查询状态返回 undone
Op_Undone --> Op_Polling : 间隔 5 秒重试 (最大3次)
}
ISSUING --> ACTIVE : 查询状态返回 success
ISSUING --> ISSUE_FAILED : 状态返回 failed 或多次 timeout
ISSUE_FAILED --> ISSUING : 管理员手动重试 / 定时补偿重试
}
state "正常使用阶段 (Active Use)" as ActiveUse {
ACTIVE --> ACTIVE : 门锁正常开门 / 查询电量信号
ACTIVE --> EXPIRED : 超过 validUntil 有效期边界
}
state "权限注销阶段 (Revoke Flow)" as RevokeFlow {
ACTIVE --> REVOKING : 学员退宿 / 提前退训 / 换房
ISSUE_FAILED --> REVOKING : 换房或作废
state REVOKING {
[*] --> Revoke_Requested : 调用 POST /online-password/delete
Revoke_Requested --> Revoke_Accepted : DMS 返回 200 (获得 operationId)
Revoke_Accepted --> Revoke_Polling : 延迟等待 10 秒
Revoke_Polling --> Revoke_Polling : undone (重试轮询)
}
REVOKING --> REVOKED : 查询状态返回 success
REVOKING --> REVOKE_FAILED : 状态返回 failed 或 timeout
REVOKE_FAILED --> REVOKING : 紧急人工重试撤销
}
REVOKED --> [*]
EXPIRED --> [*]
```
---
## 4. 关键流转分支与语义判定细节
### 4.1 成功下发分支 (Happy Path)
1. 触发下发:适配器调用 `/rest/doorlock/online-password-key/create`。
2. DMS 同步响应:
```json
{
"success": true,
"data": {
"id": 4945,
"placeId": 1320,
"lockId": 372,
"operationId": "0872887e-464b-4f44-a0cc-057871ba0f65"
}
}
```
**本地动作**:持久化 `external_key_id = 4945`,创建外部操作记录(`operationId = 0872887e...`, `status = ACCEPTED`),授权主表推进为 `ISSUING`。
3. 轮询调度器等待 10 秒:调用 `/rest/doorlock/query-operation-status`(入参 `requestType = 1`, `operationId = ...`)。
4. 轮询响应:
```json
{
"success": true,
"data": {
"operationStatus": "success"
}
}
```
**本地动作**:更新操作记录为 `SUCCESS`,授权主表推进为 `ACTIVE`(生效可用)。
### 4.2 设备超时分支 (`Timeout Handling`)
- 若 10 秒后轮询返回:
```json
{
"success": true,
"data": {
"operationStatus": "timeout",
"message": "Device response timeout"
}
}
```
- **判定规则**:门锁可能休眠过深、网关信号不佳或网关离线。
- **系统动作**:
1. 不得无限循环调用。
2. 若配置了自动补偿,可追加 1 次重试查询;若依然超时,将操作置为 `TIMEOUT`,授权主表置为 `ISSUE_FAILED`。
3. 页面以警告色徽标展示“设备下发超时”,提供【重新下发】按钮供管理员现场排障。