baa-conductor


baa-conductor / tasks / archive
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- 还有哪些剩余风险