39 lines
1.3 KiB
Markdown
39 lines
1.3 KiB
Markdown
# 文件编辑锁契约 v1
|
||
|
||
## 公共接口
|
||
|
||
```text
|
||
POST /api/v1/files/{storage_object_id}/lock
|
||
POST /api/v1/file-locks/{edit_session_id}/heartbeat
|
||
DELETE /api/v1/file-locks/{edit_session_id}
|
||
```
|
||
|
||
三个接口均要求 `X-User-ID` 和 `X-Workspace-ID`。加锁成功返回一次性原始
|
||
`lock_token`;心跳和释放请求体均为:
|
||
|
||
```json
|
||
{"lock_token": "raw-token-returned-by-acquire"}
|
||
```
|
||
|
||
原始 token 只由客户端持有,数据库只保存 SHA-256 摘要。
|
||
|
||
## MySQL 租约
|
||
|
||
`edit_sessions` 是实时锁权威:
|
||
|
||
- `session_status=active` 且 `expires_at > now()` 表示锁有效;
|
||
- 同一 `storage_object_id` 同时只能存在一个有效编辑会话;
|
||
- 心跳更新 `last_heartbeat_at` 与 `expires_at`;
|
||
- 主动释放将状态改为 `closed`;
|
||
- 后台清理将超时租约改为 `expired`。
|
||
|
||
加锁、心跳和释放都在数据库事务中校验 `edit_session_id + lock_token_hash`。
|
||
部署时 Runtime 保持单副本;若扩展到多副本,应为加锁查询增加数据库行锁或唯一
|
||
租约表约束。
|
||
|
||
## 状态与错误
|
||
|
||
- 冲突返回 HTTP 409、错误码 `FILE_LOCK_CONFLICT`,并包含当前编辑者和租约到期时间;
|
||
- 错误 token 返回 HTTP 403,且不得续期或释放现有锁;
|
||
- 浏览器建议每 15 秒心跳,默认租约为 45 秒。
|