基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-08 09:02

漏读分页游标,让客户巡检空转23天

dev.to · AI#分页#任务调度#可观测性
Editor brief · 编辑速览

客户巡检任务只请求前100条记录,未处理接口返回的 next_cursor,导致其余4312名客户连续23天未被检查。日报仍将局部扫描结果报告为正常,掩盖了覆盖范围缺失。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

一个夜间任务连续 23 天报告「检查了 100 条客户记录,零问题」,实际却一直只读第一页,把另外 4,312 名客户留在检查范围之外。作者的教训很具体:请求成功、没有报错、结果为空,都不能证明任务做完了。

这篇案例值得读,不在于分页有多难,而在于它暴露了定时任务和 Agent 的共同盲点:执行程序自己报喜,监控照单全收。要发现这种静默失败,得先定义「完成」,再拿独立证据核对。

为什么每天检查 100 条,反而应该报警

任务原本要遍历客户表,找出订阅已失效、状态仍为 active 的客户,再把更新银行卡的邮件放进队列。作者当时的实现如下:

def audit_customers():
    resp = requests.get(
        "https://api.internal.example/v1/customers",
        params={"limit": 100},
        headers={"Authorization": f"Bearer {TOKEN}"},
        timeout=30,
    )
    resp.raise_for_status()
    rows = resp.json()["data"]

    stale = [r for r in rows if r["status"] == "active" and r["renewed_at"] is None]

    for r in stale:
        queue_email(r["email"], template="card_update")

    return {"checked": len(rows), "queued": len(stale)}

要看的是 params={"limit": 100}:它限制了单次读取量,却没有配套的翻页逻辑。API 返回了 next_cursor,代码根本没读。

表里共有 4,412 条记录,任务每天重复处理同一批 100 条,其余 4,312 条没有进入审计。这里要区分:原文并没有证明这 4,312 人都应该收到邮件,只能确认他们没有被检查。

日报直接根据返回值生成「检查 100 条,零问题,一切正常」。数字是真的,结论却越过了证据。

「读了多少条」是测量值,「有没有读完」才是完成条件。

作者用了 11 分钟修复,却花了 23 天才发现。缺的不是错误日志,而是一条能让任务失败的判断:实际覆盖范围是否符合预期。

怎样让任务证明自己已经读完

作者补了三层检查。

第一层是游标分页。新的 iter_customers(page_size=100, max_pages=200) 每页读取 data,再取 next_cursor;有游标就继续,没有才正常结束。请求保留 timeout=30,后续请求带上 cursor 参数。

max_pages=200 是硬上限。达到上限仍没走到末尾,就抛出 RuntimeError。上限能防止任务无限跑,但不能成为静默截断数据的理由。

第二层是独立计数,用数据库里的数量检查 API 读取结果:

rows = list(iter_customers())
expected = db.scalar("SELECT count(*) FROM customers WHERE status='active'")
assert len(rows) >= expected, f"read {len(rows)} rows, table says {expected}"

要看最后一行:比较的是读取数量与独立查询结果,而不是继续相信任务自己返回的 checked。

作者承认这是近似检查。任务运行时数据会变,API 的过滤条件也可能与 SQL 不同。它针对的是「应有四千多条,却只读了一百条」这种巨大缺口。

第三层是修改日报。新的示例包含 4,412/4,412 条 active 记录、游标已结束、运行时间 02:14–02:19 UTC,以及入队邮件数 61。覆盖量和业务结果终于分开了:零封邮件可能正常,只读一页却未必正常。

只有分页器真正走到末尾,日报才能写完成;否则标记为 PARTIAL,任务以非零状态退出。作者还把摘要检查从执行函数中拆出,由另一个检查查询水位表(watermark table)并比较结果。不过,原文没有给出这张表的结构及具体校验逻辑。

为什么客户反馈应该先推翻绿色日报

第 23 天,一名客户反馈,自己已经连续三周收到支付失败通知。作者先怀疑服务提供商,依次检查邮件队列、模板和发送日志,花了 40 分钟才回头审视扫描任务。

这些下游环节可以全部正常。客户没有进入待处理名单,发送日志自然也不会记录相应的发送失败。

作者此前在 9 月的一次监控故障后,就写过「客户报告优先于自动报告」的规则,但绿色面板仍然影响了排查顺序。

这次他把规则改成操作步骤:客户反馈与日报冲突时,先怀疑日报,并把获取原始记录数的命令放进排障手册第一步。原文没有提供这条命令,不能照抄复现,但思路清楚:让排查入口直接触达底层数据。

重复计数也是一种廉价线索。不过,每天相同不自动等于故障。作者自己也承认,日报连续一周逐字相同,既可能业务稳定,也可能任务卡住,单看日志分不出来。

我的判断

这篇最有价值的地方,是把「完成」从一句日志变成可验证的条件。对定时任务、后台批处理和 Agent,这比调整日报措辞更有用。

但作者提出的目标是「每条符合条件的记录恰好处理一次」,展示的检查还达不到这个保证。len(rows) >= expected 只能发现部分数量缺口;重复读取可能掩盖遗漏,API 返回全部客户、SQL 只统计 active 客户时,也可能漏读后仍通过检查。原文前后对总记录数和 active 记录数的口径,也没有交代清楚。

游标正常结束同样不能单独证明业务处理完整。遍历期间数据变动、邮件重复入队、部分处理失败如何恢复,文章没有展开。示例中的 list(iter_customers()) 还会把结果全部放进内存;实际规模更大时,需要另行考虑。

因此,独立计数适合做粗粒度的异常探测,不能替代唯一 ID 去重、处理状态和必要的对账。Python 的 assert 在优化模式下还可能被移除,生产环境中的关键失败条件更适合显式判断并抛错。

这些改动是否降低了多少漏检率,作者没有提供对照数据。文末还带有付费手册推广,LAUNCH90、$1.90 和首周节省 5 小时的承诺属于营销信息,不能当作方案有效性的证据。

能拿来做什么

  • 检查现有 Node 定时任务或 Agent 中带 limit 的 API 请求,确认它会沿 next_cursor、page 或 offset 走到终点,并在达到分页上限时明确失败。
  • 给批处理分别记录读取数量、预期数量、分页结束状态和起止时间,再从独立查询获取预期值;先统一过滤条件,避免拿不同范围的数据比较。
  • 把日报中的「零问题」拆成覆盖情况与处理结果。如果任务只完成部分扫描,就明确显示 PARTIAL,让调度系统也收到失败状态。
  • 在排障手册第一步写入核对原始记录和处理状态的方法。客户反馈与日报冲突时,先验证客户是否进入过扫描范围,再查邮件模板和发送链路。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
下一篇
AI生成证明提速,Lean校验成瓶颈

资讯速览

dev.to · AI · 2026-11-08 09:02

AI 评分 8.0 / 10

相关标签

#分页#任务调度#可观测性

继续阅读

  • AI生成证明提速,Lean校验成瓶颈
  • RepoXray本地扫描依赖与MCP配置风险
  • AI 图片存储的关键是权限与生命周期