我的观察器在一个月内静默地丢弃了代理日志行。我的CI每周都报告这个问题,但我却称它为不稳定测试。

Reddit r/AI_Agents 新闻

摘要

作者描述了一个长达一个月的bug,其中代理观察器由于与文件监视器的竞态条件而静默丢弃日志行,最初被误诊为不稳定测试。修复方法是添加定期重新扫描以防止静默数据丢失。

如果你通过跟踪代理已经写入的日志文件来观察你的代理,这是一种值得你花十分钟了解的故障模式。我的运行了一个月,我的CI每周都报告它,我两次将其关闭为不稳定测试。设置:代理写入JSONL日志,一个中心节点按字节偏移跟踪它们,并将事件流式传输到查看器。一个文件监视器说“这个文件增长了”,跟踪器从它的最后偏移读取,新行被输出。很普通。 症状 一个测试间歇性失败,总是在最繁忙的矩阵行上。8月的macos/node 24。上周的ubuntu/node 24。六行中五行每次都是绿色的。测试打开观察器,启动第二个会话,等待中心节点注意到它,附加一行,并期望该行到达。我两次将其读作时间预算只是紧张,第二次我在测试文件的注释中写了这一点,这是最昂贵的错误。 什么杀死了假设 不是失败,而是失败输出。测试转储它接收的每一帧,其形状是:{“kind”:“ready”,“sessionId”:“late-sess”,“replayed”:12} {“kind”:“roster”, ...} {“kind”:“ready”,“sessionId”:“late-sess”,“replayed”:0} ... x26 二十六次在八秒内扫过,零字节读取,无错误,无重置。慢不会那样。慢最终会到达。那是一行永远不会到达的行。 机制 一个监视器异步启动自己。无论你使用fs.watch、fs.watchFile还是chokidar,在“我请求一个监视器”和“监视器已采用其基线”之间有一个窗口。在轮询模式下,基线是一个stat,之前写入的任何内容都在基线内。文件未被视为变化,因为相对于基线它从未变化。所以丢失数据的排序是:t0 赶上读取到EOF,偏移=S1;t1 行被附加,大小S2;t2 轮询器采用其基线:S2...之后没有任何东西与S2不同。我的时间戳将附加放在中心节点打开监视后2毫秒内。正好在其中。 为什么它从未恢复 这是实际的bug,是我的而不是库的。一个丢失的事件如果某物重新读取是可生存的。我有一个500毫秒的扫描来重新扫描子代理目录,它没有重新读取父日志。实时会话扫描对于已经流式传输的会话提前返回。所以主文件的唯一后备是监视器就绪事件触发的一次扫描——如果写入发生在就绪之后,那个机会已经用完了。会话中的每个文件都有一个底限,除了最重要的那个。 修复 重新扫描在同一刻度上读取主日志并重新扫描子代理。一次读取如果找不到任何东西成本一个statSync,因为当偏移已经在文件末尾时跟踪器立即返回。回归测试将监视器保持在一分钟一次轮询,因此监视器报告的任何内容都无法在测试内到达,只有扫描可以交付该行。没有修复时,它在所有平台上都是确定性失败的。 两件值得借鉴的事 将监视器视为尽力而为,并为你跟踪的每个文件提供一个定期底限。空闲时廉价,它将“静默丢失”转换为“最多延迟一个间隔”,这是不同类别的bug。并且:间歇性,仅在最繁忙的运行器上,是竞态条件的描述。不是按重试的原因。区分丢失事件和延迟事件的标志是系统是安静了还是在没有任何东西的情况下继续正确工作。
查看原文

相似文章