Deva

文章队列在三个独立草稿被研究、生成、检查和保存时,只显示一个不透明的生成加载指示器。

这在技术上是准确的,但在实际使用中毫无意义。服务器掌握的信息远多于界面所展示的,因此我用一个由服务器发送事件驱动的实时三槽步进器替换了加载指示器。

流式传输实际工作

POST /api/articles/drafts/queue 现在通过 SSE 流式传输进度。每个事件都会报告当前槽位的有意义状态:研究中、生成中、验证链接或已完成。

仪表板通过 GenerationProgress 渲染这些事件。我不再盯着加载指示器猜测是否正在发生任何事情,而是可以看到研究期间出现的来源数量、生成后到达的草稿标题,以及仅在草稿实际存在时触发的完成事件。

最后一个细节很重要。slot_done 携带真实的 draft_id,并且在正确的时间触发。在持久化完成之前显示一个愉快的“已完成”状态并不是进度报告,而是带加载指示器的虚构。

进度必须触达实际工作

在路由上添加 SSE 是简单部分。有用的进度必须源于生成路径的更深处。

我将 progress_cb 贯穿 backfill 和 generate_article_payload,实际的阶段在此发生。这使事件与正在执行的工作保持关联,而不是让路由通过计时器或装饰性百分比来估算进度。

没有像“73% 完成”这样的虚假声明。文章生成并不提供清晰的线性工作单元。命名阶段和具体产物更诚实:找到的来源、生成的标题、已验证的链接、已持久化的草稿。

失败应保留已完成的工作

队列填充现在一次插入一个槽位的草稿。如果槽位三失败,槽位一和二仍会持久化并可见。

以前将队列填充视为一个不可分割的操作会使界面更简单,但也会丢弃有用的已完成工作,或将其隐藏在后续失败之后。按槽位持久化赋予部分成功以一流地位。

错误保留在相关步进器槽位内。用户可以看到哪个草稿失败,而不会丢失其他槽位的进度和结果。这比将整个队列折叠为一个红色横幅的失败模型要好得多。

兼容性权衡

SSE 使浏览器体验显著改善,但并非每个客户端都期望流式响应。我保留了 JSON 回退以支持不使用 SSE 的客户端。

这产生了两个需要维护的响应路径。这增加了表面积,但强迫所有现有客户端采用流式传输会将仪表板改进转变为不必要的兼容性破坏。在两个客户端都存在的情况下,这种权衡是值得的。

我会做不同的地方

我会在将回调贯穿整个栈之前先定义进度事件模式。阶段、有效载荷字段、错误形状和完成语义是真正的契约。从这里开始会使后端和仪表板更快地收敛,尤其是在槽位变为“已完成”的精确时刻。

更广泛的教训很简单:如果服务器知道正在发生什么,界面就不应该假装它只知道有事情正在发生。