Commit 38728ae
committed
fix(executor): 上游流提前结束时同步归还节流名额
`max_concurrency` 的名额在 provider `stream_chat` 的 `finally` 里归还,而
`async for ... break` 不关闭 async generator——CPython 只在耗尽 / 显式
`aclose()` / GC 的 asyncgen finalizer 时才跑 `finally`。
executor `_stream_loop` 遇 `EventKind.ERROR` 的两处 `break` 于是让名额推迟
归还;轮换重试每次重新 `wait_turn`,`_inflight` 单调累积,满 3 后新请求在
`wait_turn` 无限阻塞——表现为「用了三次就限制」而非「并发三」。
这推翻了 Q45 的原始判断(`max_concurrency=0` 时泄漏只是让节流变松,配上
上限后泄漏即永久丢失许可)。修复:新增 `provider.base.aclose_stream`,
在 `stream_guarded` / `stream` / `_stream_loop` / `complete` /
`ContinuationStream.__aiter__` 五处提前结束消费点显式关闭上游流。
顺带修掉客户端断开路径的同类泄漏——此前生产环境靠 GC 及时回收侥幸未
暴露,换任何非 `with_keepalive` 的调用方就会攒满后永久卡死。
回归测试 tests/test_stream_slot_release.py(10 例,回退源码后 6 例失败)。1 parent 6a3d02c commit 38728ae
9 files changed
Lines changed: 418 additions & 41 deletions
File tree
- src
- engine
- provider
- tasks
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
53 | | - | |
| 53 | + | |
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
352 | 352 | | |
353 | 353 | | |
354 | 354 | | |
355 | | - | |
| 355 | + | |
356 | 356 | | |
357 | 357 | | |
358 | 358 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
705 | 705 | | |
706 | 706 | | |
707 | 707 | | |
| 708 | + | |
| 709 | + | |
708 | 710 | | |
709 | 711 | | |
710 | 712 | | |
| |||
0 commit comments