fix: validate memory retry attempts · openclaw/openclaw@90c2ac3
steipete
·
2026-05-29
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +import { describe, expect, it, vi } from "vitest"; |
| 2 | +import { resolveRetryConfig, retryAsync } from "./retry-utils.js"; |
| 3 | + |
| 4 | +describe("resolveRetryConfig", () => { |
| 5 | +const defaults = { |
| 6 | +attempts: 4, |
| 7 | +minDelayMs: 0, |
| 8 | +maxDelayMs: 0, |
| 9 | +jitter: 0, |
| 10 | +}; |
| 11 | + |
| 12 | +it("does not round malformed attempt counts", () => { |
| 13 | +expect(resolveRetryConfig(defaults, { attempts: 1.5 }).attempts).toBe(4); |
| 14 | +expect(resolveRetryConfig(defaults, { attempts: Number.POSITIVE_INFINITY }).attempts).toBe(4); |
| 15 | +expect(resolveRetryConfig(defaults, { attempts: Number.NaN }).attempts).toBe(4); |
| 16 | +}); |
| 17 | +}); |
| 18 | + |
| 19 | +describe("retryAsync", () => { |
| 20 | +it("falls back to the default attempt count for malformed numeric counts", async () => { |
| 21 | +const run = vi.fn(async () => { |
| 22 | +throw new Error("boom"); |
| 23 | +}); |
| 24 | + |
| 25 | +await expect(retryAsync(run, Number.NaN, 0)).rejects.toThrow("boom"); |
| 26 | + |
| 27 | +expect(run).toHaveBeenCalledTimes(3); |
| 28 | +}); |
| 29 | +}); |
| Original file line number | Diff line number | Diff line change |
|---|
@@ -48,11 +48,18 @@ function clampNumber(value: unknown, fallback: number, min?: number, max?: numbe
|
48 | 48 | return Math.min(Math.max(next, floor), ceiling); |
49 | 49 | } |
50 | 50 | |
| 51 | +function resolveAttempts(value: unknown, fallback: number): number { |
| 52 | +if (typeof value !== "number" || !Number.isSafeInteger(value)) { |
| 53 | +return fallback; |
| 54 | +} |
| 55 | +return Math.max(1, value); |
| 56 | +} |
| 57 | + |
51 | 58 | export function resolveRetryConfig( |
52 | 59 | defaults: Required<RetryConfig> = DEFAULT_RETRY_CONFIG, |
53 | 60 | overrides?: RetryConfig, |
54 | 61 | ): Required<RetryConfig> { |
55 | | -const attempts = Math.max(1, Math.round(clampNumber(overrides?.attempts, defaults.attempts, 1))); |
| 62 | +const attempts = resolveAttempts(overrides?.attempts, defaults.attempts); |
56 | 63 | const minDelayMs = Math.max( |
57 | 64 | 0, |
58 | 65 | Math.round(clampNumber(overrides?.minDelayMs, defaults.minDelayMs, 0)), |
@@ -79,7 +86,7 @@ export async function retryAsync<T>(
|
79 | 86 | initialDelayMs = 300, |
80 | 87 | ): Promise<T> { |
81 | 88 | if (typeof attemptsOrOptions === "number") { |
82 | | -const attempts = Math.max(1, Math.round(attemptsOrOptions)); |
| 89 | +const attempts = resolveAttempts(attemptsOrOptions, DEFAULT_RETRY_CONFIG.attempts); |
83 | 90 | let lastErr: unknown; |
84 | 91 | for (let i = 0; i < attempts; i += 1) { |
85 | 92 | try { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。