im_wower
·
2026-03-28
T-BUG-011.md
1# Task T-BUG-011:修复 writeHttpResponse drain 等待挂起
2
3## 直接给对话的提示词
4
5读 `/Users/george/code/baa-conductor/tasks/archive/T-BUG-011.md` 任务文档,完成开发任务。
6
7如需补背景,再读:
8
9- `/Users/george/code/baa-conductor/bugs/README.md`
10- `/Users/george/code/baa-conductor/bugs/BUG-011-writeHttpResponse-drain-handler-hangs.md`
11- `/Users/george/code/baa-conductor/bugs/FIX-BUG-011.md`
12
13## 建议分支名
14
15- `fix/bug-011-write-http-response`
16
17## 当前状态
18
19- 已完成(2026-03-27,当前代码已修复并通过自动化验证)
20
21## 目标
22
23修复 `writeHttpResponse()` 在背压后客户端提前断开时可能永久挂起的问题,并补上可复现的自动化测试。
24
25## 背景
26
27当前 `apps/conductor-daemon/src/index.ts` 里的 `writeHttpResponse()` 在 `response.write(...)` 返回 `false` 后只等待 `drain`,没有同时处理 `close` / `error`。一旦客户端在 `drain` 触发前断开,协程可能永远不返回。
28
29## 涉及仓库
30
31- `/Users/george/code/baa-conductor`
32
33## 范围
34
35- 修复 `writeHttpResponse()` 的 drain 等待逻辑
36- 覆盖普通 body 写入和 `streamBody` 循环写入两条路径
37- 增加最小但有效的自动化测试
38
39## 路径约束
40
41优先在现有实现附近修复,不要为了这个任务引入新的抽象层或大范围重构。
42
43## 推荐实现边界
44
45建议新增:
46
47- 一个局部复用的等待 helper,例如 `awaitWritableDrainOrClose(...)`
48
49建议放到:
50
51- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
52
53## 允许修改的目录
54
55- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
56- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
57
58## 尽量不要修改
59
60- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts`
61- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/browser-request-policy.ts`
62- `/Users/george/code/baa-conductor/plugins/baa-firefox/`
63
64## 必须完成
65
66### 1. 修复挂起点
67
68- 处理 `payload.body` 写入时的背压等待
69- 处理 `streamBody` 循环写入时的背压等待
70- `drain`、`close`、`error` 任一触发后都能正确清理 listener
71
72### 2. 保持旧行为
73
74- 正常慢客户端下仍能继续写完响应
75- 连接已关闭时不要继续写入或抛出新的未处理异常
76
77### 3. 补测试
78
79- 增加能覆盖 `write()` 返回 `false` 后提前断开的测试
80- 至少验证 handler 不会永久 pending
81
82## 需要特别注意
83
84- 不要只修一处,`writeHttpResponse()` 里两处 drain 等待都要覆盖
85- 不要引入 listener 泄漏
86- 不要把这次任务扩成 HTTP 层全面重构
87
88## 验收标准
89
90- 背压后客户端提前断开时,请求处理不会永久挂起
91- `payload.body` 和 `streamBody` 两条路径都被覆盖
92- 相关自动化测试通过
93
94## 推荐验证命令
95
96- `pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon build`
97- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
98
99## 完成记录
100
101- 实际修改文件:
102 - `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
103 - `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
104- 实际结果:
105 - 新增 `awaitWritableDrainOrClose(...)`
106 - `writeHttpResponse()` 的 body / stream 背压等待都改成同时处理 `drain` / `close` / `error`
107 - 已补 3 条专项测试,覆盖 body close、stream close、drain 后继续写入
108- 实际验证:
109 - `pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon build`
110 - `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`(`31/31`)
111
112## 交付要求
113
114完成后请说明:
115
116- 修改了哪些文件
117- 核心实现思路是什么
118- 跑了哪些测试
119- 还有哪些剩余风险