remove(ai): delete the composer-race post and its generator entries (user decision)
Deploy / build (push) Successful in 21s
Deploy / build (push) Successful in 21s
- git rm src/content/posts/the-dialog-opened-in-7-seconds-my-script-waited-5.md + the zh twin - drop its TERMINALS/BANNERS entries from both generators (pure deletions: 0 added, 17 + 5 removed, node --check OK, 0 remaining references to the slug, the other three slugs intact) - build still 153 pages; no route, no listing row, no sitemap entry
This commit is contained in:
1 parent
27d3dca3c3
commit
3e354cc5db
4 files changed
-289
No files matched your search
@@ -1,101 +0,0 @@
|
||||
---
|
||||
title: "对话框 7.2 秒就打开了,而我的脚本只等了 5 秒"
|
||||
description: "定时任务一直报「composer 对话框没有打开」。其实三个阶段分别挂在 1.8 秒、2.8 秒和 7.2 秒——而脚本只在第 5 秒看了一次。"
|
||||
pubDate: 2026-10-15
|
||||
category: ai
|
||||
tags: ["automation", "linkedin", "cron", "browser", "agents"]
|
||||
ogImage: /og/the-dialog-opened-in-7-seconds-my-script-waited-5.png
|
||||
banner: /banners/the-dialog-opened-in-7-seconds-my-script-waited-5.png
|
||||
draft: true
|
||||
---
|
||||
|
||||
## 一条技术上属实、方向上全错的失败消息
|
||||
|
||||
我那个定时发帖任务干不成活的时候会往我手机上发消息,那天早上它说:
|
||||
|
||||
```text
|
||||
⚠️ Cron 'linkedin-daily-post' failed: Script exited with code 1
|
||||
LinkedIn daily post — FAILED
|
||||
FAILED: the composer dialog did not open
|
||||
```
|
||||
|
||||
语气笃定、指认具体、毫无用处。没有任何内容被发出去,站点是好的,浏览器配置也还登着,而这条消息告诉我该怪谁:一个根本没出现过的对话框。
|
||||
|
||||
对话框出现了。它在我脚本判定它没出现之前 3.2 秒就已经出现了。
|
||||
|
||||
## 我先看的地方,以及为什么那是错的地方
|
||||
|
||||
一个对着网站上跑的自动化失败,通常有三个嫌疑对象:会话过期、网站改了结构、账号被限流。我先查了会话——健康。而在我自己的项目笔记里,四五天前的两次失败带着**一模一样**的消息,当时写下的工作假设是「会话可能已经死了」。
|
||||
|
||||
那句话就是线索。两次完全相同的失败、一个假设,而那个假设从未被验证过。一个反复出现、原因却没被确认的失败,是**量测问题**,不是诊断问题。
|
||||
|
||||
## 去量挂载时间,别去猜消息
|
||||
|
||||
于是我把浏览器保持在脚本留下的状态里打开 composer,给每一块 DOM 到达的时间记账:
|
||||
|
||||
```text
|
||||
+1.8 秒 composer 对话框元素存在
|
||||
+2.8 秒 Post / Proofread 按钮存在
|
||||
+7.2 秒 文本编辑器存在 <- 脚本真正要输入的那个节点
|
||||
```
|
||||
|
||||
脚本点了「开始发帖」,睡了五秒,然后看了**一次**。在第 5 秒,对话框在、按钮在、编辑器不在——而代码只有一条失败消息,用「对话框没有打开」这一句话覆盖了全部三种情况。
|
||||
|
||||
没有任何东西坏掉。是脚本在错误的时刻问了一个问题,然后把答案当成了一桩关于 LinkedIn 的事实。
|
||||
|
||||
## 修法:为你要的节点轮询,而不是为时钟
|
||||
|
||||
- **为具体节点轮询**,给 40 秒的期限,而不是睡一个固定时长再看一次。
|
||||
- **把缺失的前置条件说出来。** 现在超时会说明是对话框、按钮还是编辑器没出现。仅这一处改动就能省掉两个会话。
|
||||
- **如果对话框根本没出现,把点击重试一次。** 被吞掉的点击是另一个真实的失败模式,它值得一个与「挂载慢」不同的应对。
|
||||
- **失败时留下截图。** 下一个查这个 bug 的人应该拿到像素,而不是一句话。
|
||||
- **把编辑与校验弹窗里同一种「看一次」的写法也删掉**——那是另一个屏幕上完全相同的形状。同一个 bug 出现在第二处不是巧合,而是这段代码等待方式的模式。
|
||||
- **测试:** 新增 13 条不依赖浏览器的测试,钉住分阶段挂载与被吞掉的点击,于是将来任何重新引入 `sleep(5)` 的重构,会在 CI 里失败,而不是在我手机上失败。
|
||||
|
||||
## 第二个缺陷,只有真的发出去才看得见
|
||||
|
||||
竞态修好之后,帖子发出去了——但不是一次成功,而第二次失败更值得写。第一次点「Post」被**无视了整整 75 秒**。然后一次完全相同的点击(同样的坐标、同样的 DOM,我核对过指针事件序列确实到达了按钮的 span)在 **2 秒**内被接受。
|
||||
|
||||
一次「被送达但毫无作用」的点击,和一次「从未被送达」的点击,看起来完全一样。唯一能分辨两者的办法,是别再拿点击当证据,改拿**结果**当证据:
|
||||
|
||||
- 现在只有 composer 自己关闭,才算提交被确认;
|
||||
- 有上限的三次重试点击,并且拒绝对一个 disabled 按钮再点;
|
||||
- 提交在途时不再把标签页拆掉——所谓「清理」在请求还在飞的时候就干过这件事。
|
||||
|
||||
## bug 背后藏着的是队列问题
|
||||
|
||||
这个 bug 很吵。而下一个失败会是**无声**的。
|
||||
|
||||
我的草稿是分批审批的,每批带 72 小时有效期,而队列每天只消耗一篇。于是一批按「12 天余量」审批的草稿,在当天上午 10:36 全部过期——剩下七行全部作废。第二天早上的定时任务会发现没有可用内容,然后**什么都不发**。「再也没有工作可做」不会产生任何错误消息;一个跑空了活的调度器只会安静下来,而安静看起来就像「今天没什么好发的」。
|
||||
|
||||
我只修了那七行未使用、哈希匹配记录的过期时间,状态、哈希、载荷一个字没动——因为草稿要不要重新批准是人的决定,自动化不该自己制造同意。至于那个更彻底的修法(让审批窗口按队列的消耗速率来定,而不是按批次导入的日期),我故意留着没做。
|
||||
|
||||
## 如果重来一次
|
||||
|
||||
1. **对任何异步挂载的东西,永远不要 `sleep(n)` 之后只看一次。** 为你要的产物轮询,带期限、带具名失败。
|
||||
2. **把一个反复出现的假失败,当成「第一次诊断错了」的证据。** 「会话可能已经死了」是一个贴合症状、却从未被检验的故事。
|
||||
3. **让报错消息说出缺失的前置条件。** 含糊的消息不只是没帮助——它主动把你带偏,这一条让我去查了两天的会话和页面结构。
|
||||
4. **用结果证明提交,而不是用点击。** 输入事件不是副作用;composer 消失才是。
|
||||
5. **把队列的健康和任务的健康分开监控。** 一个运行完美却没发出任何东西的任务,跟一个正常工作的任务长得一模一样——除非你去数它产出了什么。
|
||||
|
||||
## 验证
|
||||
|
||||
| 检查项 | 结果 |
|
||||
|---|---|
|
||||
| 帖子已上线 | 已发布,从页面回读了永久链接与 activity URN |
|
||||
| 内容 | 认证态回读确认正文文字与加粗短语渲染正确 |
|
||||
| 定时任务路径 | 重跑该任务:`ok`,`failure_streak` 回到 0 |
|
||||
| 重复发布防护 | 正确拒绝第二次发布——「post cap reached: 1 done today」 |
|
||||
| 台账 | 审批被消耗,并写入一条带永久链接的 `POST_PUBLISHED` 记录 |
|
||||
| 测试 | 404 条通过,包含新增的 13 条(分阶段挂载、被吞掉的点击) |
|
||||
| 收尾 | 我的探针打开过的 11 个标签页已关闭;浏览器原有的 4 个保持原样 |
|
||||
|
||||
顺便说一句,那天真正发出去的那篇,是讲我把语音转文字跑在自己硬件上的那篇——[就是这里描述的那套「什么都是两份」的配置](/posts/self-hosted-speech-to-text-api/)。它跟这个 bug 毫无关系。而这恰恰是重点:这个任务的汇报对「发生了什么」说错了话,而错误的汇报比没有汇报更糟。
|
||||
|
||||
## 想要给你的业务做一套?
|
||||
|
||||
如果你手上有一件重复性的发布、报表或数据录入工作正由人手工在做——或者有一个「偶尔会失败」但没人知道为什么的自动化——我在自己运维的基础设施上做浏览器与 API 自动化。像这样一篇文里的工作量,大部分不在顺风路径上,而在于**把失败弄得足够诚实,以至于能被修**。
|
||||
|
||||
**WhatsApp:[+60 12-797 2969](https://wa.me/60127972969)** · **邮箱:[[email protected]](mailto:[email protected]?subject=Automation%20that%20tells%20the%20truth)** · **[hoelee.com](https://hoelee.com)**
|
||||
|
||||
我经营 Hoelee Enterprise,一家面向马来西亚中小企业的网站设计与开发公司——上面这些自动化工作,跑的就是我给客户搭建的那套基础设施。如果你正在招聘平台、DevOps 或 AI 基础设施方向的岗位,同样的渠道也能找到我。
|
||||
Reference in new issue
Block a user