docs: document migration and quota safeguards
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
237899745
2026-07-26 05:48:14 +08:00
parent 910e60ab59
commit f8f5da04db
3 changed files with 22 additions and 9 deletions

View File

@@ -315,6 +315,8 @@ Stripe 运行时还通过迁移维护三组一致性结构:
- `provider_object_event_watermarks` 以 Stripe `event.created` 和事件等级保存对象水位;同秒同等级的不同事件标记为歧义并触发权威快照,不能按 Event ID 字典序决定先后。
- `stripe_subscription_reconciliations` 保存历史非因果水位的租约化对账任务,允许多 API 实例用 `FOR UPDATE SKIP LOCKED` 安全消费。
迁移 `020` 会为尚无水位的历史 Stripe 发票写入 `requires_reconciliation=true` 哨兵。首个后续发票事件必须从 Stripe 获取当前对象后才能覆盖本地记录;`invoices_paid_at_status_check` 同时保证只有 `paid` 状态可以携带 `paid_at`
数据库唯一索引同时保证非空 `users.billing_customer_id` 全局唯一、`subscriptions(provider, provider_subscription_id)` 唯一、非空 `invoices(provider, provider_invoice_id)` 唯一,以及每用户最多一条未取消 Stripe 订阅。部署这些索引前必须先清理存量冲突,具体检查见 `docs/deployment.md`
### 4.8 tasks - 压缩任务
@@ -355,7 +357,10 @@ CREATE TABLE tasks (
zip_storage_endpoint_id UUID REFERENCES storage_endpoints(id) ON DELETE RESTRICT,
zip_storage_key TEXT,
zip_storage_etag TEXT,
zip_size BIGINT
zip_size BIGINT,
zip_build_token UUID,
zip_build_lease_until TIMESTAMPTZ,
zip_build_attempt BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_tasks_user_id ON tasks(user_id);
@@ -365,6 +370,10 @@ CREATE INDEX idx_tasks_created_at ON tasks(created_at);
CREATE INDEX idx_tasks_expires_at ON tasks(expires_at);
```
`zip_build_token/zip_build_lease_until` 是跨 API 实例的任务级 single-flight 租约。每个构建 attempt 写入独立对象键,只有 token 匹配的 CAS 更新可以发布到 `zip_storage_*`;失败或失租 attempt 必须删除对象。
匿名单文件预留单独存入 `anonymous_single_reservations`,不依赖尚未创建的 `tasks` 外键。`pending` 超时或 `refund_pending` 记录由 Worker 维护循环使用任务级 Redis marker 补偿;`charged/refunded` 记录保留 7 天后清理。
### 4.9 task_files - 任务文件
```sql
CREATE TABLE task_files (