fix: align retry backoff semantics and test mock signatures

This commit is contained in:
Peter Steinberger
2026-02-18 04:32:49 +01:00
parent 0bf1b38cc0
commit 50e5553533
5 changed files with 19 additions and 40 deletions

View File

@@ -60,10 +60,9 @@ const ANNOUNCE_EXPIRY_MS = 5 * 60_000; // 5 minutes
function resolveAnnounceRetryDelayMs(retryCount: number) { function resolveAnnounceRetryDelayMs(retryCount: number) {
const boundedRetryCount = Math.max(0, Math.min(retryCount, 10)); const boundedRetryCount = Math.max(0, Math.min(retryCount, 10));
// retryCount tracks completed failed attempts. The next retry delay should // retryCount is "attempts already made", so retry #1 waits 1s, then 2s, 4s...
// start at 1s for retry #1, then 2s, 4s, ... const backoffExponent = Math.max(0, boundedRetryCount - 1);
const exponent = Math.max(0, boundedRetryCount - 1); const baseDelay = MIN_ANNOUNCE_RETRY_DELAY_MS * 2 ** backoffExponent;
const baseDelay = MIN_ANNOUNCE_RETRY_DELAY_MS * 2 ** exponent;
return Math.min(baseDelay, MAX_ANNOUNCE_RETRY_DELAY_MS); return Math.min(baseDelay, MAX_ANNOUNCE_RETRY_DELAY_MS);
} }

View File

@@ -1,8 +1,8 @@
import { Command } from "commander"; import { Command } from "commander";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
const runAcpClientInteractive = vi.fn(async (_opts?: unknown) => {}); const runAcpClientInteractive = vi.fn(async (_opts: unknown) => {});
const serveAcpGateway = vi.fn(async (_opts?: unknown) => {}); const serveAcpGateway = vi.fn(async (_opts: unknown) => {});
const defaultRuntime = { const defaultRuntime = {
error: vi.fn(), error: vi.fn(),

View File

@@ -4,18 +4,7 @@ import type { BrowserParentOpts } from "./browser-cli-shared.js";
import { registerBrowserStateCommands } from "./browser-cli-state.js"; import { registerBrowserStateCommands } from "./browser-cli-state.js";
const mocks = vi.hoisted(() => ({ const mocks = vi.hoisted(() => ({
callBrowserRequest: vi.fn( callBrowserRequest: vi.fn(async (..._args: unknown[]) => ({ ok: true })),
async (
_opts: BrowserParentOpts,
_params: {
method: "GET" | "POST" | "DELETE";
path: string;
query?: Record<string, string | number | boolean | undefined>;
body?: unknown;
},
_extra?: { timeoutMs?: number; progress?: boolean },
) => ({ ok: true }),
),
runBrowserResizeWithOutput: vi.fn(async (_params: unknown) => {}), runBrowserResizeWithOutput: vi.fn(async (_params: unknown) => {}),
runtime: { runtime: {
log: vi.fn(), log: vi.fn(),
@@ -25,20 +14,11 @@ const mocks = vi.hoisted(() => ({
})); }));
vi.mock("./browser-cli-shared.js", () => ({ vi.mock("./browser-cli-shared.js", () => ({
callBrowserRequest: ( callBrowserRequest: mocks.callBrowserRequest,
opts: BrowserParentOpts,
params: {
method: "GET" | "POST" | "DELETE";
path: string;
query?: Record<string, string | number | boolean | undefined>;
body?: unknown;
},
extra?: { timeoutMs?: number; progress?: boolean },
) => mocks.callBrowserRequest(opts, params, extra),
})); }));
vi.mock("./browser-cli-resize.js", () => ({ vi.mock("./browser-cli-resize.js", () => ({
runBrowserResizeWithOutput: (params: unknown) => mocks.runBrowserResizeWithOutput(params), runBrowserResizeWithOutput: mocks.runBrowserResizeWithOutput,
})); }));
vi.mock("../runtime.js", () => ({ vi.mock("../runtime.js", () => ({
@@ -82,7 +62,7 @@ describe("browser state option collisions", () => {
const call = mocks.callBrowserRequest.mock.calls.at(-1); const call = mocks.callBrowserRequest.mock.calls.at(-1);
expect(call).toBeDefined(); expect(call).toBeDefined();
if (!call) { if (!call) {
throw new Error("Expected callBrowserRequest to be called"); throw new Error("expected browser request call");
} }
const request = call[1] as { body?: { targetId?: string } }; const request = call[1] as { body?: { targetId?: string } };
expect(request.body?.targetId).toBe("tab-1"); expect(request.body?.targetId).toBe("tab-1");
@@ -105,7 +85,7 @@ describe("browser state option collisions", () => {
const call = mocks.callBrowserRequest.mock.calls.at(-1); const call = mocks.callBrowserRequest.mock.calls.at(-1);
expect(call).toBeDefined(); expect(call).toBeDefined();
if (!call) { if (!call) {
throw new Error("Expected callBrowserRequest to be called"); throw new Error("expected browser request call");
} }
const request = call[1] as { body?: { headers?: Record<string, string> } }; const request = call[1] as { body?: { headers?: Record<string, string> } };
expect(request.body?.headers).toEqual({ "x-auth": "ok" }); expect(request.body?.headers).toEqual({ "x-auth": "ok" });

View File

@@ -2,12 +2,12 @@ import { Command } from "commander";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
import { addGatewayServiceCommands } from "./register-service-commands.js"; import { addGatewayServiceCommands } from "./register-service-commands.js";
const runDaemonInstall = vi.fn(async (_opts?: unknown) => {}); const runDaemonInstall = vi.fn(async (_opts: unknown) => {});
const runDaemonRestart = vi.fn(async (_opts?: unknown) => {}); const runDaemonRestart = vi.fn(async (_opts: unknown) => {});
const runDaemonStart = vi.fn(async (_opts?: unknown) => {}); const runDaemonStart = vi.fn(async (_opts: unknown) => {});
const runDaemonStatus = vi.fn(async (_opts?: unknown) => {}); const runDaemonStatus = vi.fn(async (_opts: unknown) => {});
const runDaemonStop = vi.fn(async (_opts?: unknown) => {}); const runDaemonStop = vi.fn(async (_opts: unknown) => {});
const runDaemonUninstall = vi.fn(async (_opts?: unknown) => {}); const runDaemonUninstall = vi.fn(async (_opts: unknown) => {});
vi.mock("./runners.js", () => ({ vi.mock("./runners.js", () => ({
runDaemonInstall: (opts: unknown) => runDaemonInstall(opts), runDaemonInstall: (opts: unknown) => runDaemonInstall(opts),

View File

@@ -1,9 +1,9 @@
import { Command } from "commander"; import { Command } from "commander";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
const updateCommand = vi.fn(async (_opts?: unknown) => {}); const updateCommand = vi.fn(async (_opts: unknown) => {});
const updateStatusCommand = vi.fn(async (_opts?: unknown) => {}); const updateStatusCommand = vi.fn(async (_opts: unknown) => {});
const updateWizardCommand = vi.fn(async (_opts?: unknown) => {}); const updateWizardCommand = vi.fn(async (_opts: unknown) => {});
const defaultRuntime = { const defaultRuntime = {
log: vi.fn(), log: vi.fn(),