mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 03:52:26 +08:00
fix(billing): hold inflight reservation until billing lands; price estimate like billing; wire remaining endpoints
Address gaps found in adversarial verification of the in-flight balance reservation: - Early release: the reservation is now a ref-counted handle carried on the request context. Billing tasks submitted via submit*UsageRecordTask take a ref and return it only after RecordUsage has run; with reservation enabled the balance cache is deducted synchronously inside the billing task, so the reservation is released only after admission can see the deduction. Dropped tasks return their ref immediately. The reservation is renewed every ttl/3 while the handler runs; after the handler returns it is no longer renewed, so the post-handler hold is bounded by one TTL. - Estimate: use the same billing model (channel mapping + BillingModelSource, max over requested/mapped when ambiguous) and ModelPricingResolver (group ModelPricing incl. wildcards, channel per_request/image/video/token overrides), default/group/user rate + peak multiplier, plus image, video, audio and search surcharge kinds. Unpriced requests fail open with a throttled log; new billing.inflight_reservation.fail_closed_on_unpriced (default false) rejects them instead. - Wire images, embeddings, web/x search, alpha search, grok media generation, grok realtime/voice, OpenAI-platform /v1/messages and ResponsesWebSocket (session-level reservation with renewal). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
43f88c99aa
commit
52c123e6f4
@@ -1135,8 +1135,11 @@ billing:
|
||||
# 用户无在途请求时始终放行(与旧行为一致);估算失败/Redis 不可用时 fail-open。
|
||||
inflight_reservation:
|
||||
enabled: true
|
||||
# Max lifetime of a single reservation (self-heals leaked reservations)
|
||||
# 单条预留最长存活时间(秒),泄漏的预留到期自动释放
|
||||
# Reservation TTL. Renewed every ttl/3 while the request is running; after the
|
||||
# handler returns it is held (not renewed) until the async billing task has
|
||||
# deducted the cached balance, so a stuck billing task frees it after at most one TTL.
|
||||
# 预留 TTL(秒)。请求进行中每 ttl/3 续期;请求结束后不再续期,保持到异步计费
|
||||
# 扣减余额缓存后释放,计费任务卡死时最多一个 TTL 后自动失效
|
||||
ttl_seconds: 900
|
||||
# Output tokens assumed when the request has no max_tokens
|
||||
# 请求未携带 max_tokens 时假定的输出 token 数
|
||||
@@ -1148,6 +1151,10 @@ billing:
|
||||
# Cap for a single reservation in USD (0 = no cap)
|
||||
# 单请求预留金额上限(USD,0 为不设上限)
|
||||
max_reservation_usd: 0
|
||||
# When a request cannot be priced (no base / group / channel pricing for the
|
||||
# billing model), reject it instead of admitting it without reservation.
|
||||
# 无法为请求定价(计费模型无基础/分组/渠道定价)时拒绝请求;默认 false 为放行不预留(节流告警日志)
|
||||
fail_closed_on_unpriced: false
|
||||
|
||||
# =============================================================================
|
||||
# Turnstile Configuration
|
||||
|
||||
Reference in New Issue
Block a user