refactor: integrate model platform backend

This commit is contained in:
Winnie
2026-07-30 13:43:29 +08:00
parent baee7a60e1
commit 6d6c70cea8
97 changed files with 19724 additions and 2146 deletions
+63
View File
@@ -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 释放。