refactor: integrate model platform backend
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# 文件编辑锁契约 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}
|
||||
```
|
||||
|
||||
三个接口均要求用户身份和 Workspace 身份。当前开发基线使用
|
||||
`X-User-ID`、`X-Workspace-ID`,后续接入 JWT 时保持路径和业务 DTO 不变。
|
||||
|
||||
加锁成功返回一次性原始 `lock_token`。心跳和释放请求体均为:
|
||||
|
||||
```json
|
||||
{"lock_token": "raw-token-returned-by-acquire"}
|
||||
```
|
||||
|
||||
原始 token 只由客户端持有,禁止写入 MySQL 和日志。
|
||||
|
||||
## Redis 数据
|
||||
|
||||
```text
|
||||
Key: lock:file:{workspace_id}:{storage_object_id}
|
||||
TTL: 45000 ms
|
||||
```
|
||||
|
||||
Value:
|
||||
|
||||
```json
|
||||
{
|
||||
"edit_session_id": "01J...",
|
||||
"user_id": "01J...",
|
||||
"display_name": "张三",
|
||||
"token_hash": "sha256-hex",
|
||||
"acquired_at": "UTC timestamp"
|
||||
}
|
||||
```
|
||||
|
||||
加锁必须使用:
|
||||
|
||||
```text
|
||||
SET key value NX PX 45000
|
||||
```
|
||||
|
||||
心跳和释放必须执行 Lua 原子操作,并同时比较
|
||||
`edit_session_id + token_hash`:
|
||||
|
||||
```text
|
||||
heartbeat: compare owner -> PEXPIRE 45000
|
||||
release: compare owner -> DEL
|
||||
```
|
||||
|
||||
禁止使用 `GET` 后单独 `DEL`,也禁止在 MySQL 文件表增加 `is_locked`。
|
||||
|
||||
## 状态与错误
|
||||
|
||||
- Redis 是实时锁唯一权威。
|
||||
- `edit_sessions` 记录 `active/closed/expired`,仅用于审计。
|
||||
- 冲突返回 HTTP 409、错误码 `FILE_LOCK_CONFLICT`,并包含当前编辑者及租约到期时间。
|
||||
- 错误 token 返回 HTTP 403,且不得续期或释放现有锁。
|
||||
- 浏览器建议每 15 秒心跳;关闭、断线或心跳超时后由主动释放或 TTL 释放。
|
||||
Reference in New Issue
Block a user