弱工单
给 orders report 加 CSV 导出。 大客户也要能用,导出完成后邮件通知。
这个案例把模糊导出需求改写成有权限、job 状态、文件过期和评审证据的后台任务流程。
给 orders report 加 CSV 导出。 大客户也要能用,导出完成后邮件通知。
Feature: 异步 orders report CSV 导出 Owner: Reporting Status: Draft for review 目标: - 允许 account admin 将当前 orders report 导出为 CSV。 - 超过 10,000 行的数据集走后台 job。 - 文件准备好后通知发起用户。 非目标: - 不重做 report filter。 - 不新增分析列。 - 不支持跨 account 导出。 - 不做实时 streaming download。
约束: - 导出使用页面上可见的相同 filters。 - 发起用户必须属于该 account。 - 文件 7 天后过期。 - CSV 列与当前 report table 一致。 风险: - 长查询压力 - filter snapshot 过期 - 下载链接被分享给 account 外用户
- [ ] 捕获 report filter snapshot。 - [ ] 创建 export_jobs 表和状态机。 - [ ] 增加 CSV 生成 worker。 - [ ] 增加带过期时间的 signed download URL。 - [ ] 增加 admin UI 状态:queued、running、ready、failed。 - [ ] 增加队列和失败指标。
- Given admin 筛选 orders When 请求导出 Then job 使用相同 filter snapshot。 - Given 非 admin 用户 When 请求或下载 export Then 访问被拒绝。 - Given 50 万行 report When export 运行 Then web request 快速返回,worker 异步完成。
自动化: - export permission test - filter snapshot test - job state transition test - expired download URL test 运维: - 50 万行耗时结果 - queue depth dashboard - failed job alert link
| 状态 | 允许转移 | 评审证据 |
|---|---|---|
queued | 权限和 filter snapshot 校验后创建。 | 测试证明 job 存储 account id、user id 和 filters。 |
running | Worker claim 一个 job,并写入进度 metadata。 | 测试证明两个 worker 不能处理同一 job。 |
ready | CSV 已存储,并生成 signed URL。 | 证据证明 URL 会过期,并检查 account 权限。 |
failed | Worker 记录安全错误,用户可以重试。 | PR 中链接 alert 和 failed-job metric。 |
弱需求说的是“加 CSV 导出”,但真正的风险不是按钮,而是按钮之后发生什么:长查询阻塞 Web 请求、用户在 job 运行时修改筛选条件、文件链接在用户失去权限后仍可访问,或后台失败无人发现。
规格包把导出变成状态机,而不是一个 UI 装饰。后台任务和普通请求的失败位置不同,所以评审者需要在合并前看到权限检查、filter snapshot、文件过期、队列监控和失败路径。
请求和下载都要确认用户属于该 account。只在请求时检查一次不够。
导出的 CSV 应匹配用户点击导出时可见的筛选条件,而不是后续编辑后的条件。
队列深度、失败任务、重试率和 worker 耗时,应该在上线前可见。
导出、导入、批量操作、对账任务、账单运行、数据回填,以及任何“用户发起、稍后完成”的流程,都可以使用这个模式。可复用的是状态机和证据清单,而不是具体业务领域。
对于小导出,10,000 行阈值可以调低,也可能不需要邮件通知。但不应该消失的是 Web 请求和 worker 的边界、下载时权限检查,以及大客户不会拖慢主应用的证据。
让 AI 编码助手实现这类工作时,不要允许它顺手引入队列库、重做报表或添加额外字段。那些都是独立决策,需要另一份规格。第一版规格包只保护安全导出行为。
报表导出不能因为 staging 下载成功一次就算完成。第一版上线时应该有观察计划,因为真实账号规模、真实筛选条件和真实重试行为,往往才会暴露问题。规格里应写清首日观察什么信号,以及信号异常时采取什么动作。
这个案例里,最有价值的信号包括 queue depth、worker duration、failed job count、download permission failure,以及客服是否收到“少列、错列、筛选条件不一致”的反馈。回滚动作也要具体:关闭导出按钮、暂停 worker,或保留已完成文件但阻止新请求。
还要提前写清 owner。工程负责人看 worker 和数据库压力,产品负责人确认导出列和筛选语义,客服负责人收集用户反馈。没有 owner 的观察计划很容易变成“上线后看看”,最后没人真正看。
队列深度和 worker 耗时能证明导出没有拖慢其他后台任务。
权限失败和过期链接事件能证明下载安全逻辑被真实触发。
少列、错列或筛选条件不一致的反馈,说明导出文件没有匹配用户预期。
异步导出跨越产品、后端、前端、运维和客服。如果规格只写实现任务,不写谁负责判断结果,评审会在最后一刻才发现缺口。一个可执行的导出规格应明确:谁确认字段顺序,谁验证权限,谁观察队列,谁处理失败 job,谁决定是否关闭入口。
这个职责分工不需要复杂流程,但必须具体。比如“Reporting owner 在首日每两小时查看 failed job 仪表盘”,“Support owner 记录导出文件缺列反馈”,“Engineering owner 在 queue depth 超过阈值时暂停 worker”。这些句子比“上线后监控”更有价值,因为它们能真正触发行动。
大客户会遇到超时或数据库压力。长任务应异步执行。
Signed URL 仍需要 account-aware 访问规则,或短过期时间和安全再生成路径。
用户和客服需要知道导出是失败、可重试,还是需要工程介入。
这个案例关注异步任务:规格的价值在于让后台状态、权限和运维证据在实现前可见。