refactor: route TPM reservation and settlement through the derived value
Five call sites (QuotaGate entry, RetryMW/EmbeddingClient success and transient-failure settlement) now read effective_est_tokens() instead of est_tokens. Success paths gain an unavailable branch that keeps delta at zero once usage frames may be missing; it has no producer yet, so behaviour is unchanged while the tpm>0 => est_tokens>0 gate still holds.
This commit is contained in:
@@ -268,7 +268,11 @@ class EmbeddingClient:
|
|||||||
source_name=source.name,
|
source_name=source.name,
|
||||||
operation="embedding",
|
operation="embedding",
|
||||||
)
|
)
|
||||||
actual = result.prompt_tokens
|
if result.usage_source == "unavailable":
|
||||||
|
# 与 RetryMW 同口径: 用量不可得时按入场预扣量结算(设计 §3.2 #9)
|
||||||
|
actual = source.effective_est_tokens()
|
||||||
|
else:
|
||||||
|
actual = result.prompt_tokens
|
||||||
await self._record_quietly(self._breaker.record_success(entry))
|
await self._record_quietly(self._breaker.record_success(entry))
|
||||||
await self._record_quietly(self._quota.mark_progress())
|
await self._record_quietly(self._quota.mark_progress())
|
||||||
latency_ms = int((self._now() - started) * 1000)
|
latency_ms = int((self._now() - started) * 1000)
|
||||||
@@ -291,7 +295,8 @@ class EmbeddingClient:
|
|||||||
reasons[source.name] = reason
|
reasons[source.name] = reason
|
||||||
await self._record_quietly(self._breaker.record_failure(entry, reason, dead))
|
await self._record_quietly(self._breaker.record_failure(entry, reason, dead))
|
||||||
if not dead:
|
if not dead:
|
||||||
actual = source.est_tokens # 保守: 失败请求可能已被网关计费(CHS 同款)
|
# 保守: 失败请求可能已被网关计费(CHS 同款);与入场预扣同源取值
|
||||||
|
actual = source.effective_est_tokens()
|
||||||
await self._emit(batch, source, call_id, started, session_id, parent_call_id, error=exc)
|
await self._emit(batch, source, call_id, started, session_id, parent_call_id, error=exc)
|
||||||
return _FailedBatch(exc, immediate=dead)
|
return _FailedBatch(exc, immediate=dead)
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class QuotaGate:
|
|||||||
|
|
||||||
async def try_acquire(self, source: SourceConfig) -> Permit | None:
|
async def try_acquire(self, source: SourceConfig) -> Permit | None:
|
||||||
try:
|
try:
|
||||||
return await self._limiter.try_acquire(source.name, source.est_tokens)
|
return await self._limiter.try_acquire(source.name, source.effective_est_tokens())
|
||||||
except GovernanceBackendError:
|
except GovernanceBackendError:
|
||||||
raise
|
raise
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@@ -335,7 +335,12 @@ class RetryMW:
|
|||||||
overlay=request.overlay,
|
overlay=request.overlay,
|
||||||
call_id=call_id,
|
call_id=call_id,
|
||||||
)
|
)
|
||||||
actual = result.prompt_tokens + result.completion_tokens
|
if result.usage_source == "unavailable":
|
||||||
|
# 用量不可得时按入场预扣量结算(delta==0),否则押金会被整笔退回,
|
||||||
|
# 对"从不返回 usage 帧"的源等于 TPM 闸失效(设计 §3.2 #9)
|
||||||
|
actual = source.effective_est_tokens()
|
||||||
|
else:
|
||||||
|
actual = result.prompt_tokens + result.completion_tokens
|
||||||
await self._record_quietly(self._breaker.record_success(entry))
|
await self._record_quietly(self._breaker.record_success(entry))
|
||||||
await self._record_quietly(self._quota.mark_progress())
|
await self._record_quietly(self._quota.mark_progress())
|
||||||
self._feed_outcome(source.name, ok=True)
|
self._feed_outcome(source.name, ok=True)
|
||||||
@@ -367,7 +372,8 @@ class RetryMW:
|
|||||||
self._pacer.on_backpressure(source.name)
|
self._pacer.on_backpressure(source.name)
|
||||||
await self._record_quietly(self._breaker.record_failure(entry, reason, dead))
|
await self._record_quietly(self._breaker.record_failure(entry, reason, dead))
|
||||||
if not dead:
|
if not dead:
|
||||||
actual = source.est_tokens # 保守: 失败请求可能已被网关计费(CHS 同款)
|
# 保守: 失败请求可能已被网关计费(CHS 同款);与入场预扣同源取值
|
||||||
|
actual = source.effective_est_tokens()
|
||||||
await self._emit(request, source, call_id, started, error=exc)
|
await self._emit(request, source, call_id, started, error=exc)
|
||||||
return _Failed(exc, immediate=dead)
|
return _Failed(exc, immediate=dead)
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
Reference in New Issue
Block a user