fix: WithDefaultTimeout 不再套用到流式输出/双向流

流式输出(Invoke[chan T])返回的 channel 由调用方通过 range 自行决定
消费多久,典型场景是流式聊天回复,可能正常持续几十秒甚至更久。之前
WithDefaultTimeout 会不分场景地把这个全局默认超时套到整个调用生命周期
上(包括流还在正常输出的过程中),导致长时间运行的正常流式响应被腰斩。

改成流式输出/双向流完全不受 WithDefaultTimeout 影响,只认调用方显式传入
的 ctx deadline;需要超时保护的话必须自己 context.WithTimeout。普通调用
和流式输入不受影响,继续吃池子的默认超时。

新增 TestStreamOutIgnoresDefaultTimeout 验证;example/main.go 的
demoTimeout 补充示例4 演示这一行为;README 同步更新。
This commit is contained in:
2026-07-23 14:24:10 +08:00
parent 4f74627be1
commit 6ccec66a1e
4 changed files with 57 additions and 23 deletions
+25
View File
@@ -177,6 +177,31 @@ func TestStreamErrorMidwayCorruptsNextCall(t *testing.T) {
}
}
// TestStreamOutIgnoresDefaultTimeout 验证 WithDefaultTimeout 不会套用到流式输出/
// 双向流调用上:流式聊天这类响应可能持续很久,如果套用全局默认超时会在正常输出
// 过程中把它腰斩。没有显式传入 deadline 时,流式调用应该完全不受池子默认超时影响,
// 只受调用方显式设置的 ctx 约束。
func TestStreamOutIgnoresDefaultTimeout(t *testing.T) {
pool := newTestPool(t, WithWorkers(1), WithMaxConns(1), WithDefaultTimeout(200*time.Millisecond))
// slow_range_gen(1, 10, 100) 总耗时 ~900ms,远超 200ms 的默认超时。
// 用 context.Background()(无 deadline)发起调用:如果默认超时被错误地套用到
// 流式输出上,channel 会在 ~200ms 提前关闭,读不满 9 个元素。
ch, err := Invoke[chan int](context.Background(), pool, "slow_range_gen", 1, 10, 100)
if err != nil {
t.Fatalf("Invoke: %v", err)
}
var got []int
for v := range ch {
got = append(got, v)
}
if len(got) != 9 {
t.Fatalf("want 9 items (WithDefaultTimeout 不应影响流式输出), got %v", got)
}
}
// TestStreamInputCancelDoesNotLeakThread 验证流式输入模式下,handler 线程阻塞在
// _ChunkIter.__next__ → chunk_q.get() 等待下一个输入块时,如果 ctx 取消导致连接被
// Go 关闭,Python 侧能否真正把这个线程唤醒退出,而不是永久卡住。