Commit Graph
21 Commits
Author SHA1 Message Date
what ee5e5b96af 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
看输出,现在都有真实断言。
2026-07-23 16:24:05 +08:00
what 6ccec66a1e fix: WithDefaultTimeout 不再套用到流式输出/双向流
流式输出(Invoke[chan T])返回的 channel 由调用方通过 range 自行决定
消费多久,典型场景是流式聊天回复,可能正常持续几十秒甚至更久。之前
WithDefaultTimeout 会不分场景地把这个全局默认超时套到整个调用生命周期
上(包括流还在正常输出的过程中),导致长时间运行的正常流式响应被腰斩。

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

新增 TestStreamOutIgnoresDefaultTimeout 验证;example/main.go 的
demoTimeout 补充示例4 演示这一行为;README 同步更新。
2026-07-23 14:24:10 +08:00
what 4f74627be1 fix: 修复流式输入 ctx 取消时 handler 线程永久阻塞泄漏的问题
流式输入模式下,handler 线程阻塞在 _ChunkIter.__next__ → chunk_q.get()
等待下一个输入块时,如果 ctx 取消导致 Go 关闭连接,_ConnMux._reader
原来只往 call_q 推了 None、给 _active_tids 里的线程注入 InterruptedError,
没有处理 chunk_q。而 PyThreadState_SetAsyncExc 打断不了阻塞在
queue.Queue.get()(无 timeout)上的线程,因为它是纯 C 层等待、不会回到
字节码解释循环检查待处理异常,导致这个线程永久卡死、泄漏。

修复:连接关闭时也往 chunk_q 推一个 None 哨兵,_ChunkIter.__next__ 已经
把 None 当作流结束处理,会正常抛 StopIteration 让线程退出。

新增 pool_test.go 里的 TestStreamInputCancelDoesNotLeakThread 复现并验证
修复(通过对比 count_threads() 前后线程数)。python 包版本号同步升到 0.1.5。
2026-07-23 14:07:47 +08:00
what eb6ebd8632 test: 补充 WithEnv 环境变量注入的测试
验证 WithEnv 设置的变量能真正传进子进程,避免上层配置解析漏掉该
字段时无法被发现(此前 framework-v2 里 env 字段一直未接入,线上因
此从未真正生效过)。
2026-07-23 13:48:34 +08:00
what 983d106166 fix: 修复流式 handler 中途抛异常时 end/error 消息错位的问题
_dispatch 处理生成器(yield)handler 时之前用 try/finally 包裹迭代,
导致中途抛异常时会先发一条 end、再发一条 error。Go 侧 invokeStreamOut
读到第一条终止消息(end)就直接返回并把连接标记健康放回池子,遗留的
error 消息留在 socket 里,会被下一个复用该连接的调用错误地当成自己的
响应读走,造成两次完全不相关的调用结果串号。

改成不用 finally,只在生成器正常耗尽后发送一次 end;异常直接交给外层
统一处理发送 error,保证一次调用只产生一条终止消息。

新增 pool_test.go 里的 TestStreamErrorMidwayCorruptsNextCall 复现并验证修复。
2026-07-23 13:44:45 +08:00
what 0f4a4ded53 feat: 添加 WithDefaultTimeout 默认超时配置
Invoke 之前完全依赖调用方传入的 ctx 控制超时,池子被占满或 Python 侧
handler 阻塞时,未设置 deadline 的调用会永久阻塞且不报错。新增
WithDefaultTimeout 选项,仅在 ctx 未设置 deadline 时兜底生效,调用方
显式设置的超时优先级更高。

同时补充 example 中的阻塞/超时演示(demoTimeout、demoBlocking)和
pool_test.go 集成测试,覆盖池占满排队、默认超时、显式 deadline 优先级、
流式输出超时后 channel 静默关闭等场景。
2026-07-23 10:37:24 +08:00
what db71a904e0 feat: 添加全局错误日志捕获
- Python 侧 _dispatch 异常时输出完整堆栈到 stderr
- Go 侧 handler 返回 error 时打印日志
- 升级 Python 包版本至 0.1.4
2026-05-20 19:30:52 +08:00
what 16261a8c8f chore: 升级 Python 包版本至 0.1.3 2026-05-19 20:09:18 +08:00
what 57775a33ec feat: 添加 []byte ↔ bytes 支持(base64 透明编解码)
- Python 侧:_decode_bytes_args 根据函数注解自动解码入参,_bytes_encode 自动编码 bytes 返回值
- _cast 支持 bytes 类型(call_go[bytes] 返回值解码)
- 流式输出同步支持 chan []byte(每个 chunk 独立编解码)
- example/worker.py 新增 bytes_reverse / bytes_concat / bytes_chunks 示例
- example/main.go 新增对应演示用例
- README 补充类型表 []byte 行及完整使用章节
2026-05-19 20:07:31 +08:00
what e6a61cc1ee refactor: 将 WithSticky 重命名为 StickyCtx,避免与 pool Option 的 With* 前缀冲突 2026-05-08 15:21:59 +08:00
what a3cf983b39 refactor: 将 WithAffinity 重命名为 WithSticky,文件 affinity.go → sticky.go 2026-05-08 11:37:34 +08:00
what 3d293699e9 docs: 添加 Session 亲和路由章节(NewSession / WithAffinity) 2026-05-08 11:29:39 +08:00
what cda662e874 feat: 添加 Session 亲和路由支持(NewSession / WithAffinity)
- 新增 NewSession(pool):返回固定到同一 worker 进程的 Pool 视图
- 新增 WithAffinity(ctx, key):相同 key 通过 FNV hash 稳定路由到同一 worker
- pool.acquire 支持亲和路由,无亲和时保持轮询
- example 添加 Session / WithAffinity / 全局变量共享三组演示
2026-05-08 11:21:02 +08:00
what 30004e44ee docs: 添加 handler 中使用 threading.Thread 的注意事项 2026-04-14 16:49:12 +08:00
what b4e77ce9a8 feat: 为 Python worker 输出添加行前缀,并启用无缓冲模式
- 新增 prefixWriter,对每行输出添加 [python:N] 前缀,便于与 Go 日志区分
- 注入 PYTHONUNBUFFERED=1,确保 print() 实时输出不被管道缓冲
2026-04-14 14:38:24 +08:00
what 39517dc5fc feat: 通过匿名管道实现父进程死亡检测,替代轮询方案
- worker.go: 为每个子进程创建 death pipe,Go 持有写端
- __init__.py: run() 中监听管道读端 EOF,Go 退出时立即终止子进程
- 解决 Ctrl+C / panic / SIGKILL 等场景下 Python worker 变成孤儿进程的问题
- Python 包版本升至 0.1.2
2026-04-14 13:49:33 +08:00
what b390effd8e feat: 添加 Python→Go 全双工回调支持(call_go)
- 新增 WithHandlers 选项,通过反射将 Go 结构体方法暴露给 Python
- 新增 callback/callback_result 消息类型,支持 Python 在处理中回调 Go
- client 侧新增 readResult,内联处理 callback,复用同一连接避免死锁
- Python 侧新增 call_go[T]() 泛型调用,支持 dataclass 自动构造
- 注入 GOBRIDGE_WORKER_ID/WORKER_COUNT 环境变量,支持多 worker 初始化分工
- 新增示例演示 Go→Python→Go→Python 四层全双工链路
- Python 包版本升至 0.1.1
2026-04-14 13:06:50 +08:00
what 07e9239ac5 refactor: 将装饰器 gobridge 重命名为 expose,并添加 pyproject.toml 2026-04-13 17:13:54 +08:00
what 308faa95ff refactor: 将 Pool 重构为接口,提取 pool 为具体实现 2026-04-10 16:38:37 +08:00
what cca4860df0 docs: 更新 uv pyproject.toml 示例,改为从 git 仓库安装 Python 包 2026-04-10 09:28:05 +08:00
what a92abca252 first commit 2026-04-10 09:24:28 +08:00