feat: 添加 WithStreamErrors 查询流式调用执行过程中的异常

流式输出/双向流的 handler(Python 生成器)如果执行过程中抛异常,
Invoke[chan T] 本身的 err 只描述"调用有没有发起成功",跟这个异常
无关(永远是 nil),channel 只会静默提前关闭,调用方原本完全无法
感知。新增 WithStreamErrors(ctx) 返回一个包过的 ctx 和一个查询函数
streamErr,opt-in 之后可以查到具体错误。

错误记录挂在 WithStreamErrors 返回的 ctx 的对象图里(context.WithValue),
不是全局表——调用方不再引用 ctx/channel 时会被 GC 自然回收,不需要
任何显式清理逻辑,也不依赖 ctx.Done(),即使用 context.Background()
也能正常释放;ctx 之后被别的 context.With*(包括 StickyCtx)再包一层
也不影响查询。

同时补充完整的自动化测试覆盖 example/main.go 里演示过的所有功能:
四种调用模式 × int/struct/slice/[]byte 的组合(client_test.go)、
WithHandlers/call_go 全双工(handlers_test.go)、NewSession 隔离性
与 StickyCtx 路由(session_test.go),之前这些只能靠人肉跑 go run
看输出,现在都有真实断言。
This commit is contained in:
2026-07-23 16:24:05 +08:00
parent 6ccec66a1e
commit ee5e5b96af
9 changed files with 717 additions and 5 deletions
+4 -2
View File
@@ -65,10 +65,12 @@ def double_stream(numbers: Iterator[int]) -> Iterator[int]:
@expose
def stream_then_raise(n: int) -> Iterator[int]:
"""流式输出中途抛异常,用于复现 _dispatch 里 end/error 消息错位的问题"""
"""流式输出执行过程中抛异常(还没 yield 完就失败),
用于复现 _dispatch 里 end/error 消息错位的问题"""
for i in range(n):
if i == n - 1:
raise ValueError(f"boom: stream_then_raise 在第 {i} 个元素时失败")
yield i
raise ValueError("boom: stream_then_raise 中途失败")
# ── structdataclass / dict)类型 ───────────────────────────────────────────