fix: settle cancelled attempts against the source estimate
取消发生在"端口已开始、结算尚未确定"时,原先按 settle(0) 把入场预扣整笔 退还,等于把可能已被上游计费的用量退回闸里;启用调用期限后库自身会常规性 触发该路径,故先修记账再启用。 改动只落在取消路径的取值上(设计 §6.3 矩阵 S3/S5/S7): - actual 初值保持 0,另设函数内局部阶段变量 settlement_known(不进任何签名); - 成功路径算出用量后置位,真实 usage 恰为 0 同样算"已知",不被取消覆写; - 已处理领域失败分支把结算决定前移到其第一个 await 之前(同级 except CancelledError 接不住本块 await 上的取消,它直穿 finally), 故 SourceDead 的既有 0 在取消下被保住,瞬时失败仍是 est,值与 1.3.5 逐字相同; - 未被四分类接住的异常不经上述分支,仍按 0 退全款(S8,本版不扩大语义); - OCR 的 0 token 是事实而非未知,settle(0) 不变,只补注释。 取消窗口一律用真实 asyncio.Event 钉死(不再 sleep 撞窗口),并加防越界回归: RuntimeError 逃逸仍结 0、真实 usage 为 0 的成功仍结 0。
This commit is contained in:
@@ -60,6 +60,8 @@ class ScriptedOcrTransport:
|
||||
def __init__(self, script):
|
||||
self.script = list(script)
|
||||
self.calls = []
|
||||
# 取消用例的确定性窗口: 进入 hang 分支即置位, 不用 sleep 撞窗口
|
||||
self.entered = asyncio.Event()
|
||||
|
||||
async def _next(self, method, source, call_id):
|
||||
self.calls.append((method, source.name, call_id))
|
||||
@@ -67,6 +69,7 @@ class ScriptedOcrTransport:
|
||||
if isinstance(action, Exception):
|
||||
raise action
|
||||
if action == "hang":
|
||||
self.entered.set()
|
||||
await asyncio.Event().wait()
|
||||
return _TEXT_OK if action == "text" else _LAYOUT_OK
|
||||
|
||||
@@ -395,6 +398,20 @@ class TestCancellation:
|
||||
stats = await limiter.source_stats("m1")
|
||||
assert stats.inflight == 0 # permit 在 finally 释放
|
||||
|
||||
async def test_cancel_in_flight_still_settles_zero(self):
|
||||
"""S6: OCR 的 0 token 是**事实**而非"未知", 取消也不得改成按 est 结算。"""
|
||||
transport = ScriptedOcrTransport(["hang"])
|
||||
client, limiter, _ = _client(
|
||||
[_src(max_concurrency=1, tpm=1000, est_tokens=400)], [], transport=transport
|
||||
)
|
||||
task = asyncio.create_task(client.recognize_text(b"jpg"))
|
||||
await transport.entered.wait()
|
||||
task.cancel()
|
||||
with pytest.raises(asyncio.CancelledError):
|
||||
await task
|
||||
stats = await limiter.source_stats("m1")
|
||||
assert stats.tpm_used == 0 and stats.inflight == 0
|
||||
|
||||
|
||||
class TestCheckHealth:
|
||||
class _HealthTransport(ScriptedOcrTransport):
|
||||
|
||||
Reference in New Issue
Block a user