fix: 修复流式 handler 中途抛异常时 end/error 消息错位的问题
_dispatch 处理生成器(yield)handler 时之前用 try/finally 包裹迭代, 导致中途抛异常时会先发一条 end、再发一条 error。Go 侧 invokeStreamOut 读到第一条终止消息(end)就直接返回并把连接标记健康放回池子,遗留的 error 消息留在 socket 里,会被下一个复用该连接的调用错误地当成自己的 响应读走,造成两次完全不相关的调用结果串号。 改成不用 finally,只在生成器正常耗尽后发送一次 end;异常直接交给外层 统一处理发送 error,保证一次调用只产生一条终止消息。 新增 pool_test.go 里的 TestStreamErrorMidwayCorruptsNextCall 复现并验证修复。
This commit is contained in:
@@ -336,11 +336,15 @@ def _dispatch(mux: _ConnMux, msg: dict):
|
||||
result = fn(*args)
|
||||
|
||||
if inspect.isgenerator(result):
|
||||
try:
|
||||
for item in result:
|
||||
mux.write({"id": msg_id, "type": "chunk", "data": _bytes_encode(item)})
|
||||
finally:
|
||||
mux.write({"id": msg_id, "type": "end"})
|
||||
# 注意:end 只能在生成器正常耗尽后发送一次。之前这里用 try/finally 包裹,
|
||||
# 导致生成器中途抛异常时会先发 end、再被下面的 except 发一条 error——
|
||||
# Go 侧读到第一条终止消息(end)就会返回并把连接标记健康放回池子,
|
||||
# 那条多余的 error 消息留在 socket 里,会被下一个复用该连接的调用错误地
|
||||
# 当成自己的响应读走。改成不用 finally,异常直接交给下面统一处理,
|
||||
# 保证一次调用只产生一条终止消息。
|
||||
for item in result:
|
||||
mux.write({"id": msg_id, "type": "chunk", "data": _bytes_encode(item)})
|
||||
mux.write({"id": msg_id, "type": "end"})
|
||||
else:
|
||||
mux.write({"id": msg_id, "type": "result", "data": _bytes_encode(result)})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user