fix(qa): clamp cron run poll intervals · openclaw/openclaw@83597b7
steipete
·
2026-05-31
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +import { MAX_TIMER_TIMEOUT_MS } from "openclaw/plugin-sdk/number-runtime"; |
1 | 2 | import { describe, expect, it, vi } from "vitest"; |
2 | | -import { waitForCronRunCompletion } from "./cron-run-wait.js"; |
| 3 | +import { resolveCronRunPollIntervalMs, waitForCronRunCompletion } from "./cron-run-wait.js"; |
3 | 4 | |
4 | 5 | describe("waitForCronRunCompletion", () => { |
5 | 6 | it("ignores older entries and returns the newly finished run", async () => { |
@@ -50,4 +51,28 @@ describe("waitForCronRunCompletion", () => {
|
50 | 51 | }), |
51 | 52 | ).rejects.toThrow(/timed out waiting for cron run completion/); |
52 | 53 | }); |
| 54 | + |
| 55 | +it("clamps oversized poll intervals before sleeping", () => { |
| 56 | +expect(resolveCronRunPollIntervalMs(Number.MAX_SAFE_INTEGER)).toBe(MAX_TIMER_TIMEOUT_MS); |
| 57 | +}); |
| 58 | + |
| 59 | +it("keeps oversized poll intervals within the overall timeout", async () => { |
| 60 | +const callGateway = vi |
| 61 | +.fn< |
| 62 | +(method: string, rpcParams?: unknown, opts?: { timeoutMs?: number }) => Promise<unknown> |
| 63 | +>() |
| 64 | +.mockResolvedValue({ |
| 65 | +entries: [{ ts: 100, status: "ok", summary: "older run" }], |
| 66 | +}); |
| 67 | + |
| 68 | +await expect( |
| 69 | +waitForCronRunCompletion({ |
| 70 | + callGateway, |
| 71 | +jobId: "dreaming-job", |
| 72 | +afterTs: 150, |
| 73 | +timeoutMs: 5, |
| 74 | +intervalMs: Number.MAX_SAFE_INTEGER, |
| 75 | +}), |
| 76 | +).rejects.toThrow(/timed out waiting for cron run completion/); |
| 77 | +}); |
53 | 78 | }); |
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import { setTimeout as sleep } from "node:timers/promises"; |
2 | 2 | import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; |
| 3 | +import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime"; |
3 | 4 | |
4 | 5 | type QaCronRunLogEntry = { |
5 | 6 | ts?: number; |
@@ -13,6 +14,10 @@ type QaCronRunsPage = {
|
13 | 14 | entries?: QaCronRunLogEntry[]; |
14 | 15 | }; |
15 | 16 | |
| 17 | +export function resolveCronRunPollIntervalMs(intervalMs: number | undefined): number { |
| 18 | +return resolveTimerTimeoutMs(intervalMs ?? 1_000, 1_000, 0); |
| 19 | +} |
| 20 | + |
16 | 21 | export async function waitForCronRunCompletion(params: { |
17 | 22 | callGateway: ( |
18 | 23 | method: string, |
@@ -25,7 +30,7 @@ export async function waitForCronRunCompletion(params: {
|
25 | 30 | intervalMs?: number; |
26 | 31 | }) { |
27 | 32 | const timeoutMs = params.timeoutMs ?? 90_000; |
28 | | -const intervalMs = params.intervalMs ?? 1_000; |
| 33 | +const intervalMs = resolveCronRunPollIntervalMs(params.intervalMs); |
29 | 34 | const startedAt = Date.now(); |
30 | 35 | let lastEntries: QaCronRunLogEntry[] = []; |
31 | 36 | while (Date.now() - startedAt < timeoutMs) { |
@@ -49,7 +54,11 @@ export async function waitForCronRunCompletion(params: {
|
49 | 54 | if (completed) { |
50 | 55 | return completed; |
51 | 56 | } |
52 | | -await sleep(intervalMs); |
| 57 | +const remainingMs = timeoutMs - (Date.now() - startedAt); |
| 58 | +if (remainingMs <= 0) { |
| 59 | +break; |
| 60 | +} |
| 61 | +await sleep(Math.min(intervalMs, remainingMs)); |
53 | 62 | } |
54 | 63 | throw new Error( |
55 | 64 | `timed out waiting for cron run completion for ${params.jobId}: ${formatErrorMessage(lastEntries)}`, |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。