Skip to content

throttled-py 可读容量配置 DSL —— 实施方案

基于 README.md 制定。

0x01 调研

a. 主流库调研结论(2026-04-04 快照)

主要语法模式单规则语法多规则语法(同一 cell 换行)适配提示
limits字符串:n/unitn per unitparse("1/minute")parse_many("1/second; 5/minute")
分隔符:逗号 ,、分号 ;、竖线(pipe)
可直接作为 quota.parse 设计参考
Flask-Limiter字符串:n per unit@limiter.limit("1 per day")default_limits=["2 per minute", "1 per second"]说明“多规则列表”体验在框架侧很常见
slowapi字符串:n/unit@limiter.limit("5/minute")@limiter.limit("5/minute")
@limiter.limit("100/hour")
limits 语法一致性高
django-ratelimit短字符串:n/us/m/h/drate='5/m'@ratelimit(..., rate='10/s')
@ratelimit(..., rate='100/m')
短语法对配置项长度友好
fastapi-limiter对象:Rate + DurationLimiter(Rate(2, Duration.SECOND * 5))Depends(RateLimiter(...Rate(1, Duration.SECOND * 5)))
Depends(RateLimiter(...Rate(2, Duration.SECOND * 15)))
非 DSL,但多规则组合方式可借鉴
pyrate-limiter对象:Rate + DurationRate(5, Duration.SECOND * 2)rates=[Rate(3, 1000), Rate(4, 1500)]内核表达力强,适合作为内部模型
aiolimiter数值参数:(max_rate, time_period)AsyncLimiter(100, 30)多个 limiter 实例并用适合极简场景,不适合作为 DSL 参考主轴

b. 调研结论

  • 生态主流形态是“请求数 + 时间单位”的短字符串表达。
  • n/unitn per unit 是最值得优先兼容的两种写法。
  • 多规则串联在 limits 中已有成熟实践,可作为解析层能力参考。

0x02 方案设计

a. 决策共识

  • 语法兼容:向前兼容 limitsn/unitn per unit
  • 能力边界:parse 支持多规则;Throttled(quota=...) 暂不支持多规则执行。
  • 版本定位:优先稳定单规则主路径,后续再开放多规则执行。

b. 单位模型与归一化

标准单位兼容写法时长
seconds, sec, secs, second, seconds1s
minutem, min, mins, minute, minutes60s
hourh, hr, hrs, hour, hours3600s
dayd, day, days86400s
weekw, wk, wks, week, weeks604800s
  • 不支持 monthyear 等非固定时长单位。
  • 解析后统一映射到内部标准单位,避免执行层语义分叉。

c. burst 语义与默认规则

  • burst 关键字语法:<rate> burst <n>
  • 默认规则:若未显式声明 burst,默认取同一规则中的 n
    • 示例:1/s 等价于 1/s burst 1
  • 生效算法:TOKEN_BUCKETLEAKING_BUCKETGCRA

d. 多规则与分隔策略

  • 推荐分隔符:;(规则间分隔)。
  • 兼容分隔符:, 与竖线(pipe)。
  • 多规则解析能力仅在 parse 层开放。
  • Throttled(quota="...") 传入多规则时返回明确错误,不做隐式降级。

e. 错误与兼容策略

  • 错误信息包含:非法片段、期望格式、可选示例。
  • 对现有对象式配置(rate_limiter.per_* / Quota)保持兼容,不做破坏性变更。
  • 同一输入在 sync / async 下保持一致解析与一致判定。

f. 文档与示例落地规范

  • 文档主路径采用字符串配置表达,不引入用户难理解术语。
  • Quick Setup 采用 pattern-first 展示,明确 4 种模式:
    • n / unit
    • n / unit burst <burst>
    • n per unit
    • n per unit burst <burst>
  • 文档示例优先 literalinclude 引用 examples,避免重复维护。

0x03 实施步骤

  1. 定义字符串语法规范,锁定单位映射、分隔符和 burst 默认规则。
  2. 实现 quota.parse(),支持单规则与多规则解析。
  3. 实现 Throttled(quota="...") 单规则适配,并对多规则输入抛出明确错误。
  4. 增加解析成功与失败测试,覆盖边界值与兼容场景。
  5. 增加单位归一化测试与 burst 默认值测试。
  6. 更新 README / docs / examples,补充迁移示例与反例说明。

0x04 验收与验证

  • 目标用例:uv run pytest -n auto tests/rate_limiter/test_quota_parser.py tests/test_throttled.py tests/asyncio/test_throttled.py
  • 全量回归(2026-04-06):uv run pytest -n auto tests/,结果 679 passed, 51 skipped
  • 门禁:uv run prek run --files ...ruffruff-formatmypy-strict)。
  • 文档:cd docs && uv run make html 构建通过。

0x05 实施进展(表格)

时间结论调整概要改动
2026-04-05[1] 解析能力归类到 rate_limiter 领域,不新增顶层 quota 兼容层。
[2] 语法兼容 n/unitn per unit
[3] parse 支持多规则,Throttled 暂不支持多规则执行。
[1] 新增 throttled/rate_limiter/quota_parser.py
[2] Throttled 接入字符串 quota
[3] 新增 tests/rate_limiter/test_quota_parser.py,并补充 sync/async 相关用例。
2026-04-05[1] 统一 burst 语法为关键字空格 <rate> burst <n>
[2] 保留逗号分隔符兼容(与 limits 一致)。
[1] 解析规则调整并补充测试。
[2] 文档中同步语法决策说明。
2026-04-06[1] 文档结构采用 pattern-first。
[2] 字符串模式下 burst 默认取同一规则中的 n(如 1/s == 1/s burst 1)。
[3] 结论性规则并入方案设计主干,避免“追加修正”割裂阅读。
[1] docs/source/quickstart/quota-configuration.rst 重构并修复 Malformed table
[2] README.md / README_ZH.md quota 区块统一为字符串主路径,并补充默认 burst 规则。
[3] examples/quickstart(含 async)统一 quota 字符串写法。
2026-04-06[1] PR 内过程性结论统一收敛到本 PLAN.md
[2] PR review threads 全部标记 resolved(含已采纳与有结论不改动项)。
[3] 针对 DSL 变更完成全量回归复验。
[1] 精简 PR conversation / inline 过程记录并改为指向 PLAN
[2] resolved review threads:quota_parser 分隔符讨论、BaseThrottledMixin 类型收敛讨论、文档 discoverability 讨论。
[3] 复验:679 passed, 51 skipped

0x06 参考

0x07 版本锚点

  • 分支:feat/260405_quota_parser_dsl
  • PR:#141