docs: record MySQL lease queue (#9)

This commit is contained in:
ila
2026-08-20 23:56:23 +08:00
parent 7dfb528166
commit d61d73d96f
2 changed files with 23 additions and 5 deletions
+12 -2
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Architecture-and-Code-Map
wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Architecture-and-Code-Map.-
wiki_revision: 97f301d12a81b734a80c90b77feaed79373248c1
synchronized_at: 2026-08-20T15:35:54Z
wiki_revision: b27a47e30cb5d79f6a6146e067a20296e850f8ab
synchronized_at: 2026-08-20T15:50:13Z
<!-- gitea-wiki-mirror:end -->
# 架构与代码地图
@@ -76,6 +76,16 @@ MVP-0 第一张上传图自动作为 `primary`,其余为 `reference`;不提
- 图片保存前同时限制总字节、声明 MIME、实际解码格式和像素数;原图校验后保存,并生成最长边 256px 的 PNG 缩略图。文件不作为公开静态目录,授权判断仍由 portal 按 metadata 和数据库归属执行。
- imaging 固定 v1.6.2,`golang.org/x/image` 提升并固定为与 go-admin 基线一致的 v0.41.0;测试只使用 mock DNS、`net.Pipe`、构造密钥和临时目录。
### #9 已落地的 MySQL 租约队列
- `internal/core/queue.MySQLRepository` 在事务中按 `(status, lease_until, created_at)` 使用 `FOR UPDATE SKIP LOCKED` 取一条 pending 或过期 running;租约比较和截止时间统一使用 MySQL `NOW(6)`,避免应用时钟偏差。
- claim 原子写 `running/lease_owner/lease_token/lease_until` 并追加 attempt 起始项;过期 running 重领不回退 pending,而是在同一 UPDATE 中把旧 attempt 标为 `lease_expired` 后追加新项。
- worker 选定唯一启用 ProviderModel 后必须先用当前 token 调用 `AssignProvider`;成功/失败 CAS 只有当前 attempt 已绑定模型时才允许。重复绑定相同模型按当前 token 核对后视为幂等成功。
- 成功在事务中先执行 `id + status=running + lease_token` CAS,再写 outputs;输出约束失败会回滚终态。失败用单条 UPDATE 同时写状态、分类 error 和脱敏限长 attempt。旧 token 的绑定、成功和失败均影响 0 行。
- 同用户创建先锁 `users` 行,再查询 `(user_id,idempotency_key)`,因此并发重放返回原 generation 且不写第二份 inputs;不同用户可使用相同 key。
- `queue.Controller.StopClaims` 与 claim 使用读写锁,停止返回后不再进入新的数据库 claim;已经在途的最终写入仍必须通过 token CAS。
- MySQL 8.4.8 集成测试在 `REPEATABLE-READ` 下覆盖双 worker、过期重领、attempt 链、旧 token、事务回滚、并发幂等和 fixture 清理;不使用 mock SQL 代替数据库门禁。
## 代码地图
| 想改什么 | 从哪里开始读 | 必要验证 |
+11 -3
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Local-Development-and-Verification
wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Local-Development-and-Verification.-
wiki_revision: c26069b43dadcab393678caf8f579c13cfa90068
synchronized_at: 2026-08-20T15:08:16Z
wiki_revision: 52051ea9898e7ee1b4f502cb77906aa105163ce7
synchronized_at: 2026-08-20T15:55:34Z
<!-- gitea-wiki-mirror:end -->
# 本地开发与验证
@@ -170,7 +170,15 @@ go run ./portal
## 测试策略
- 迁移:空 MySQL 8 隔离库逐个/全量 up-down-up,验证索引、外键、唯一约束和种子幂等。
- 队列:并发认领、租约过期重新认领、旧 token 最终写 0 行、优雅退出、attempt 原子性。
- 队列:并发认领、租约过期重新认领、旧 token 最终写 0 行、优雅退出、attempt 原子性。从 #9 起该项必须连接迁移后的隔离 MySQL 8,mock SQL 不能替代。
```powershell
$env:CHORUS_TEST_DSN = $env:CHORUS_DSN
go test -v -count=1 ./internal/core/queue/...
go test -race -count=1 ./internal/core/queue/...
$env:CHORUS_TEST_DSN = $null
```
- Provider:全部 retryable 类别使用 mock,不消耗真实额度。
- SSRF:IPv4/IPv6 私网、DNS rebinding、redirect 链、环境代理、结果 URL。
- 安全:密码/session/CSRF、登录节流、跨用户任务与文件、错误脱敏、密钥轮换。