用途与实际影响
这项功能怎样使用
为什么需要它
文件同名不代表内容相同,输出还在也不代表它完整。客户端窗口超时还可能留下正在执行的工作;如果不先定位任务就重试,会重复占用显卡,还可能混淆两次结果。
举个实际例子
我可以问:“刚才那份扫描件等超时了,现在要不要重新提交?”系统会先查原任务:仍在处理就继续等待或由我取消,已经完成就直接读取结果,确实中断才明确说明。它不会因为窗口等超时就重复跑一份。
最后我会得到什么
先得到原任务现在是处理中、完成还是中断;完整旧结果能核对时直接取回,否则才决定重新识别。部分页面证据可以帮助排查,但不是任何故障都能自动续跑。
正常时
旧结果与这份文件和要求确实相同、文件完整时直接复用。
发现问题时
等待窗口超时先查原任务,取消或中断后留下状态,不盲重交。
入口不可用或证据不足时
任务仍占资源或连终态都无法确认时停止新提交,先核对现场。
从哪里开始
在同一 LocalOCR 对话中提供刚才返回的任务标识,先问“现在进行到哪”;不要仅凭等待窗口超时重新提交。
需要准备什么
- 原任务标识或原件
- 本次识别要求
- 继续等待还是取消的选择
从开始到拿到结果
- 1
先找原任务
系统查询活跃状态和已保存结果,确认原件及请求是否仍相同。
- 2
按真实状态处置
在跑则继续查询或精确取消;正式结果完整有效则直接复用。
- 3
必要时才重试
中断或输入改变才重新执行,并区分部分证据、缓存和完整结果。
技术实现与依据
这里保留实现、关键条件、精确入口、历史记录和验证结果。
任务定位与结果复验已实现关键规则与设计选择
使用 results[].output_files 指向的正式文件,不靠同名兼容副本判断。
相同请求仍需复核输出,缓存命中只代表可复用。
当前已有逐页原子检查点和部分证据读取;它们不等于任意长 PDF 自动断点续跑,更不能在用户取消后自动重试。
本模块用到的名词
- request identity(请求身份)
- 输入、模型和请求参数的组合,防止同名文件或不同模型共享错误结果。
- formal output(正式输出)
- 本次请求完成并通过相应检查的结果路径;与兼容显示副本和 partial 初步证据不同。
- observer(只读观察)
- 让调用方看阶段、模型与时间,不替它创建或重新执行任务。
专业定义
查询、取消、复验与结果复用有同一套身份;窗口超时不是重交信号。
解决什么
防止重复执行、旧结果错配、坏缓存被接受,以及等待期限与执行期限混为一谈。
当前怎样实现
- 任务身份绑定源路径/内容、请求语义、逐页路由、具体 profile、实际权重、实现/运行库和输出目录;开发源码改变不自动改变已激活冻结版本。
- service.py 在正式写盘前后维护任务状态,复用时检查客观文件及所有输出的非空大小和 SHA-256,不只判断文件存在。
- 正式文件名包含请求身份;无哈希同名 TXT/MD/JSON 仅供兼容展示,不能作为缓存或原件身份依据。
- server.py 暴露 /jobs/<job_key> 与指定 cancel 入口;active_localocr_task 返回 409,调用方应读取原任务,不隐式新建队列。
- 增强或执行失败可以保存首轮文字与 checkpoints.py 的逐页部分证据,仍是 partial 而非完整成功缓存;取消响应标 terminal/non-retryable。
- observer.py 提供只读阶段、模型、页进度和耗时投影;这不是另一套任务调度,也不提供 OCR(光学字符识别) token 生成速率。
- OCRService 初始化调用 job_registry.recover_abandoned:复核遗留锁对应的进程身份,确认执行者已死亡才将 running 标成 failed / owner_exited 并清除占用;活任务不会仅因运行时间长被接管,不产生页级自动续跑。
- 若失败终态本身无法写入,service.py 保留恢复锁并记录 terminal_persistence_failure;health 返回 not-ready / job_state_persistence_failed,后续请求以 503 拒绝,不能把状态未落盘的服务继续当正常执行器。
执行流程
- 1
从本次原件与请求确定任务身份。
- 2
复验已有结果,完整有效时直接复用。
- 3
已有活跃任务时返回明确定位,不并发重交。
- 4
确需新执行时由同一服务负责处理与状态。
- 5
超时或中断后先查原任务和文件,再决定等待、精确取消或有界重试。
边界
- 客户端 timeout(等待超时)不证明服务端任务终止。
- 不承诺永久任务档案或跨任意故障的自动续跑。
- write_outputs=false 不登记正式写盘任务与结果缓存,内存证据不能冒充已保存证据。
失败与恢复
- HTTP 409 / active_localocr_task
- 读取已返回的 job_key 和查询入口,不盲目重复提交。
- 输出丢失、为空或指纹不匹配
- 不接受缓存命中,保留原件与请求依据后重新判断执行。
- 客户端 exit 124
- 先回查服务端任务状态;不能仅凭退出码认定识别失败。
- 增强失败但有首轮文字
- 明确为 partial,不把这些文件提升为正式成功结果。
- 服务崩溃遗留 running 与锁
- 下次启动核对进程身份;已死亡的执行标 owner_exited 并解除占用,活执行保留,不自动重跑。
- 任务终态无法写入
- 保留恢复锁与原始/落盘错误,health 标不可继续接单;先修复实际存储问题,不以进程存在或盲重提掩盖。
真实入口
E:\Projects\Tools\LocalOCR\localocr\job_registry.py任务身份与缓存复验
E:\Projects\Tools\LocalOCR\localocr\service.py正式结果提交与初步证据
E:\Projects\Tools\LocalOCR\localocr\server.py查询和精确取消
E:\Projects\Tools\LocalOCR\localocr\observer.py只读观察
如何验证
- 任务、输出、观察和进程测试分别覆盖当前行为;普通测试不能证明真实长文档的恢复速度。
- 重跑同一合成请求可验证复用,但不能据此推导任意私人原件准确率。
- 现行源码含逐页检查点、取消终态和缓存工件身份合同;9 月 17 日 Windows 同源普通 OCR(光学字符识别) 的首次与 cache_hit 输出哈希一致,不代表私人长文档或自动逐页续跑已经验收。
与其他模块的关系
结果与复核模块定义什么才算有效结果,本模块决定是否复用;运行与资源模块负责活动执行和终止边界。
