一次自动化发布到掘金的技术复盘

5 阅读3分钟

一次自动化发布到掘金的技术复盘

背景与目标

团队在构建一个内容自动化分发 pipeline,目标是实现高置信度的内容自动发布到掘金平台,同时通过钉钉接收状态通知。整个链路涉及 worker 调度、置信度判定、人工审核兜底、自动发布和通知回执多个环节。

架构链路

整体流程如下:

  1. 内容生成 → 2. Worker 调度 → 3. 置信度判定 → 4. 分发决策(高置信度自动发布 / 低置信度人工审核)→ 5. 掘金 API 调用 → 6. 钉钉通知 → 7. 状态清理

核心依赖:

  • Supabase 作为任务队列和状态存储,任务表包含 group_idstatusconfidenceretry_count 等字段
  • DingTalk Webhook 用于发送通知
  • Juejin APIopenapi.juejin.cn)用于发布草稿

踩坑与修复

问题一:置信度提取错误

现象:任务状态显示 confidence: null,导致所有任务都进入人工审核流程。

原因:最初直接从 JSON 响应体中读取 data.confidence,但后端返回的实际字段是 data.result.confidence_level。两个字段名不匹配。

修复:调整字段提取逻辑为 response.data.result.confidence_level,并在解析前增加默认值 0。这个字段名差异来自后端 API 的实际返回结构。

问题二:Juejin 分类/标签参数问题

现象:调用 POST /article/publish 返回 400 错误,提示参数校验失败。

原因:掘金 API 的分类 ID 和标签 ID 需要使用平台定义的数字 ID,而非字符串名称。最开始传入了 category_name: "frontend"tag_names: ["react"],但正确格式是 category_id: 681103670099995 这类数字 ID。

修复:建立本地映射表,将可读名称转换为平台要求的数字 ID。

问题三:publish 响应解析错误

现象:发布接口返回 200,但任务状态仍标记为 "pending",未触发成功通知。

原因:响应体结构是 { code: 0, data: { article_id: "xxx" } },但代码判断的是 response.success 或 HTTP 状态码。掘金返回 200 时 code 字段为 0 才表示成功,code: 4 表示参数错误,code: 6 表示内容敏感。

修复:增加对响应体中 code 字段的解析,将 code === 0 作为成功判定条件。

问题四:Supabase 偶发 502 干扰观测

现象:部分请求返回 502 Bad Gateway,导致任务状态更新失败,误以为发布链路中断。

原因:Supabase 在高并发写入或冷启动时偶发 502,通常是瞬时的。

修复:增加重试机制(retry_count <= 3),并在成功发布后主动清理之前的失败记录,避免失败状态累积。

问题五:高置信度结果 DingTalk 通知未发送

现象:一条高置信度任务自动发布成功后,钉钉未收到任何通知。

原因:通知逻辑只在 status === "published" 时触发,但任务完成后状态实际更新为 "success"(两个状态名不一致),导致通知分支未执行。

修复:将通知触发条件调整为 status === "success" || status === "published",确保状态更新和通知发送一致。

验证结果

已验证至少一条高置信度任务成功走通全链路:

  • 任务 group_id: xxxx 从生成到自动发布
  • 状态更新为 success
  • 钉钉收到文本通知:【发布成功】article_id: xxx, group_id: xxxx
  • 掘金后台可见该草稿已发布

边界与注意事项

  1. 置信度阈值的设定:当前设定 confidence >= 8 为高置信度自动发布,低于此阈值需人工审核。该阈值是经验值,不同内容类型可能需要调优。

  2. 重试上限:失败重试限制为 3 次,超过后人工介入。这避免无限重试导致的资源浪费。

  3. 通知去重:成功和失败通知使用不同的消息模板,失败通知包含 retry_count,便于定位问题。

  4. 敏感词过滤:掘金 API 会返回 code: 6 标记内容敏感,当前未做本地预检,依赖平台返回后人工处理。