Skip to content

DbJobAdapter 把「handler 没抛错」记成 sys_job_run.status='success' —— 内部自行降级的 job(如 wait 唤醒打空)在作业审计面上仍显示成功 #5548

Description

@os-zhuang

发现于 #5529 的实测过程(PR 见该 issue),与该修复相邻但不同面 —— 这是 job 域的审计面问题,不是 automation 域的。

观察(实测,非推断)

DbJobAdapter.wrap()(packages/services/service-job/src/db-job-adapter.ts L161-176)只按 handler 是否抛错判定运行结果:

try { await handler(ctx); finishRun(runId, 'success'); bumpJob(name, 'success'); }
catch { finishRun(runId, 'failed', msg); bumpJob(name, 'failed', msg); throw err; }

对于「内部自行处理失败、不抛错」的 handler,这条路径把它记成成功。实测(临时 harness,已删除):一个 once job 的 handler 正常返回但什么也没完成,sys_job 行是

{"name":"flow-wait:run1:pause","active":true,"schedule_expression":"2026-08-05T16:45:20.837Z","last_status":"success","run_count":1}

sys_job_run 只有一行 status: 'success'

#5529 的 wait 唤醒正是这种 handler:engine.resume()返回码报错(AutomationResult.code)而不抛错,所以 STORE_UNAVAILABLE(这一枪打空、run 仍挂在 wait 节点)在 sys_job_run 上和「成功唤醒」完全一样。

为什么可能值得看

sys_job / sys_job_run 是机器可读面(Studio 的作业界面读它)。一种读法是 sys_job_run.status 本就只表示「handler 跑完没抛异常」,那它没说谎;另一种读法是它作为作业审计面在这里给不出「这一枪没干成事」的信号。两种读法都成立,所以这里只做记录、不预判严重度。

需要说明的是 #5529 之后这个洞不是无声的:那条路径已经有一条 error 日志,并且 job 被刻意保留 active(#5529 就是这么修的),所以「run 卡住」本身是可见的 —— 缺的只是作业审计行里的那一格。因此按观察类归档(finding,不进 pm:queue),严重度交分诊判定。

可能的方向(未决,不在本 issue 范围内实施)

佐证

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions