(directory, sessionID, args = {})
| 1049 | if (job.maxRuntimeMs > 0 && current - created >= job.maxRuntimeMs) return current |
| 1050 | if (job.intervalMs === 0) return current |
| 1051 | if (!job.lastRunAt) return current |
| 1052 | return job.lastRunAt + (job.intervalMs || 0) |
| 1053 | } |
| 1054 | |
| 1055 | function nextDueDelay(state) { |
| 1056 | const current = now() |
| 1057 | let soonest = Infinity |
| 1058 | for (const job of state.jobs || []) soonest = Math.min(soonest, jobDueAt(job, current)) |
| 1059 | if (!Number.isFinite(soonest)) return Infinity |
| 1060 | return Math.max(0, soonest - current) |
| 1061 | } |
| 1062 | |
| 1063 | async function startWatchdog(directory, client, sessionID) { |
| 1064 | if (watchdogTimers.has(sessionID)) return |
| 1065 | const timer = setInterval(() => { |
| 1066 | Promise.resolve() |
| 1067 | .then(async () => { |
| 1068 | const state = await readState(directory, sessionID) |
| 1069 | const delay = nextDueDelay(state) |
| 1070 | const hasJobs = (state.jobs || []).some((job) => job.enabled !== false && !job.paused && (!isGoalJob(job) || !["completed", "blocked", "cleared"].includes(job.goalStatus))) |
no test coverage detected