文档修改

This commit is contained in:
Shen Wei
2026-04-29 15:43:49 +08:00
parent c3f9de5f9f
commit b2aadf771a
28 changed files with 7502 additions and 109 deletions

View File

@@ -267,7 +267,79 @@ Fonrey 优先采用“预签名上传 + 回执提交commit”两段式。
---
## 9. 与模块文档的衔接规则
## 9. 乐观锁Optimistic Locking规范
### 9.1 适用场景
`properties``clients``complexes` 三张高竞争表的更新操作(`PUT`/`PATCH`**MUST** 使用乐观锁并发控制,防止"后写覆盖先写"数据丢失。
### 9.2 请求规范
客户端发起更新时MUST 在请求体中携带当前资源版本号:
```json
{
"data": {
"sale_price": 180,
"version": 3
}
}
```
> 兼容说明:当前 Fonrey 为内部 Web / Electron 客户端,采用请求体传递 `version` 字段,无需 `If-Match` Header避免 HTMX 额外配置复杂度)。未来若提供对外开放 REST API可补充支持 `If-Match: <version>` Header 形式。
### 9.3 服务端执行规范
服务端执行 UPDATE 时 MUST 同时匹配 `version`,并将 `version` +1
```sql
UPDATE properties
SET sale_price = :sale_price,
version = version + 1,
updated_at = NOW(),
updated_by = :operator_id
WHERE id = :id
AND version = :client_version -- 乐观锁匹配
AND deleted_at IS NULL;
```
- 若受影响行数 **= 1**:更新成功,返回 `200`
- 若受影响行数 **= 0**:抛 `ConflictError`,返回 `409` + code `*_VERSION_CONFLICT`
### 9.4 冲突响应规范
```json
{
"ok": false,
"error": "已被他人修改,请刷新重试",
"code": "PROPERTY_VERSION_CONFLICT",
"details": {
"field": "version",
"your_version": 3,
"hint": "请重新获取最新数据后再提交"
},
"meta": {
"request_id": "uuid",
"timestamp": "2026-04-28T10:00:00+08:00"
}
}
```
- HTTP 状态码 MUST 为 `409`
- `code` 格式:`<MODULE>_VERSION_CONFLICT`(如 `PROPERTY_VERSION_CONFLICT` / `CLIENT_VERSION_CONFLICT` / `COMPLEX_VERSION_CONFLICT`
- 前端 SHOULD 展示 Toast**「已被他人修改,请刷新重试」**,并自动触发资源重新加载
### 9.5 Check List
- [ ] `version` 字段在 GET 响应中 MUST 返回(供后续 PUT/PATCH 携带)
- [ ] 服务层 update 方法 MUST 校验受影响行数0 行时抛 `ConflictError`
- [ ] 前端表单 MUST 在隐藏域中保存 `version`,随 PUT/PATCH 提交
- [ ] HTMX 场景:冲突时后端 MUST 返回 `HX-Trigger: {"toast:error":"已被他人修改,请刷新重试"}`
- [ ] 测试 MUST 覆盖:并发两次更新同版本,第二次 MUST 返回 `409`
---
## 10. 与模块文档的衔接规则
- 各模块技术方案中的“四、API 设计原则”“六、关键 API 规范”“十二、错误码建议”必须引用本文件
- 模块文档可补充模块特有 code 与字段,但不得与本规范冲突