Files
openchamber/packages/web/bin/lib/cli-control.test.js
T
Bohdan Triapitsyn b6c58df949 fix(cli): give worktree provisioning a timeout that fits the work
Creating a session with a worktree reported "Request to /api/openchamber/control
timed out after 4000ms" while the worktree was in fact created, leaving the user
with a failure message, a real worktree, and no session id. Reported alongside
worktree creation appearing to take forever.

The client HTTP timeout was extended only when the caller asked to wait for the
session. Provisioning a worktree is slow on its own: it runs git against the
repository and prepares a new directory. Measured on a cold path immediately
after a restart it takes about four seconds, which lands exactly on the four
second default and explains why this failed intermittently rather than always.
A warm run finishes in well under two.

The timeout now follows the work being requested rather than only the wait
flag, and covers whichever of the two windows is longer. The server always
completed the operation, so nothing about the outcome changes: only the client
stops abandoning it.

Verified by creating a worktree on the cold path immediately after a restart,
which previously failed here: 4004 ms and 1376 ms, both reported ok.
2026-08-04 01:33:56 +03:00

39 lines
1.5 KiB
JavaScript

import { describe, expect, it } from 'vitest';
import { resolveControlTimeoutMs } from './cli-control.js';
describe('resolveControlTimeoutMs', () => {
it('keeps the short default HTTP timeout for instant control calls', () => {
expect(resolveControlTimeoutMs({}, {})).toBeUndefined();
expect(resolveControlTimeoutMs({ wait: false, timeout: 30 }, {})).toBeUndefined();
});
it('outlives the default server wait window when wait is set', () => {
expect(resolveControlTimeoutMs({ wait: true }, {})).toBe(630_000);
});
it('derives the HTTP timeout from an explicit wait timeout in seconds', () => {
expect(resolveControlTimeoutMs({ wait: true, timeout: 30 }, {})).toBe(60_000);
});
it('never shrinks an explicitly requested HTTP timeout', () => {
expect(resolveControlTimeoutMs({ wait: true, timeout: 30 }, { timeoutMs: 5000 })).toBe(5000);
});
it('allows a worktree to be provisioned without waiting for the session', () => {
expect(resolveControlTimeoutMs({ worktree: 'feature' }, {})).toBe(120_000);
});
it('ignores a blank worktree name', () => {
expect(resolveControlTimeoutMs({ worktree: ' ' }, {})).toBeUndefined();
});
it('covers worktree provisioning even when the wait window is shorter', () => {
expect(resolveControlTimeoutMs({ wait: true, timeout: 30, worktree: 'feature' }, {})).toBe(120_000);
});
it('keeps a longer wait window when it outlasts worktree provisioning', () => {
expect(resolveControlTimeoutMs({ wait: true, worktree: 'feature' }, {})).toBe(630_000);
});
});