fuzhengwei / fuzhengwei/WaLiAPI

配额 429 错误体按端点协议返回并携带 used/limit;两轨配额记账口径合一 + 递增封顶

Open
#78 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
128
Forks
39
Avg merge
15h 25m
Merged PRs (30d)
44

Description

### 现状(如实声明)

五端点(chat / messages / responses / embeddings / models)内联检查与 `route_plan::authorize_request` 的配额拦截**从 v0.1.x 起就存在**,且有现成测试。本 issue **不引入配额强制**,只解决四个残余缺口:

1. 429 错误体 message 均为干瘪的 "Quota exceeded",不携带 used/limit 数值——使用方与管理员无从得知差多少;
2. chat 端点 429 是纯文本,而 responses/embeddings 返回 OpenAI JSON、messages 返回 Anthropic JSON——同一把 Key 超限在不同端点得到不同形状,客户端解析必须分叉;
3. legacy 转发轨(proxy 循环)只在上游返回真实 usage 时递增配额——上游不回 usage 时该轨已算好的本地估算值只写日志不入账,与新轨(endpoint_executor 有估算兜底)口径不一致,legacy 轨系统性少记;
4. 递增是无封顶纯加法,并发窗口内 quota_used 可越过 limit。

### 方案

- 五端点配额拒绝统一改用**各自协议的既有错误构造器**(`openai_error` / `anthropic_error` / `models_error`),message 走共享模板携带 `used X / limit Y` 数值;不发明新错误结构。
- `PlanError::QuotaExceeded` 携带 (used, limit),规划期错误文案同模板;429 状态码与「Key 维度终态、不做渠道 failover」语义不变。
- legacy 轨递增条件由「上游返回 usage」改为「最终入账 total_tokens > 0」——该值已含 2xx 缺失 usage 时的本地估算(与新轨共用同一 estimate_usage 模块),两轨口径合一。
- `increment_quota` 的 UPDATE 加 `CASE WHEN` 封顶:limit > 0 时取 `MIN(quota_used + ?, limit)`,否则纯加法;六处调用点自动受益。
- `quota_limit = -1`(不限)与 0 行为零影响(纯加法路径,回归通过)。

### 已知行为声明

配额检查在请求前、递增在响应后,并发窗口内多请求可同时放行;封顶后越界幅度有界(本地单实例 + SQLite 单写者,可接受)。已在代码注释显式声明。

### 测试

五端点 429 协议形态断言(OpenAI/Anthropic 形状 + message 含 used/limit);封顶三态(limit=-1/0/>0);legacy 轨 mock 上游无 usage 的估算入账集成测试。

### 开放点(征求意见)

1. `quota_reset_period`(按日/月自动重置)是否需要?
2. 配额拒绝是否补 `Retry-After` 头(当前无自动重置周期,未加)?
3. chat 端点 401 纯文本是否一并统一为 JSON(独立小改,本 PR 未含)?

---
对应分支:`feat/capability-c01-quota-harden`(无迁移)。

Contributor guide

No contributing guide indexed for this repository

Research direction

Trace the five endpoint quota checks, route_plan::authorize_request, endpoint_executor's estimate_usage, the legacy proxy loop, and increment_quota. Run the existing quota tests and add coverage for protocol-specific 429 bodies, all three limit states, and legacy responses without usage. Done means used/limit appear in the established error shapes, both accounting paths agree, and positive limits are capped.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sqlite
Domain
api, backend, databases, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.