test(e2e): widen the channel-worker sandbox budgets (#14587)

* test(e2e): widen the channel-worker sandbox budgets (#14584)

The channel-less-boot scenario starts a nested Docker-sandbox ACP session
that loads the linked channel extension (#10318), so its cost is bounded by
the daemon's initialize budget rather than by the fixture's host-side work.
Run 39121969242 spent 139.9s across three attempts on a contended
sandbox:docker shard - one attempt hit the 60s ceiling - while the same test
passes in 16.3s on a healthy docker shard and the same job's sandboxed CLI
starts took 22-26s each.

Raise the fixture's initialize budget from 60s to 120s and the scenario's
ceiling from 60s to 240s. Every assertion and input is unchanged; only the
ceilings move.

* fix(channel): let the worker's daemon requests outlast a slow sandbox start

The channel worker's DaemonClient used the SDK's 30s default request budget,
which also caps POST /session - the call that waits for the ACP child's
initialize inside the workspace sandbox. That client deadline, not the
daemon's initialize budget, is what turned a slow start into
"Could not create task": #14584's failing attempts returned about 40s after
the test began, worker connect plus the 30s cutoff.

Give the worker a request budget that covers a 120s sandbox-scale initialize
budget with headroom. prompt() is already exempt from fetchTimeoutMs, and the
supervisor's own startup/delivery budgets stay at 30s, so only the daemon
calls that can legitimately be slow get the wider window.

Refs #14584.

* test(e2e): correct the channel-worker budget comment (#14584)

The fixture no longer matches qwen-serve-routes.test.ts - the sibling fixtures
stay at 60s - and the 240s ceiling absorbs two full 120s starts, not four: the
scenario creates two tasks before the daemon restart and reloads both after.
Say both plainly.

* revert: drop the client-wide request budget in favor of #14588

The client-wide fetchTimeoutMs also capped session resume at 180s, so a daemon
advertising a restore budget above 170s regressed, and it bypassed #14588's
derived session-operation deadline for the very caller that hit the bug. #14588
owns the client-side deadline; this PR keeps only the fixture ceilings, which
the third failed attempt needed on its own.

Refs #14584, #14588.

* test(e2e): give the channel-worker ceiling room for the scenario's fixed cost

The 240s ceiling was exactly 2 x 120s, so two slow starts at the full budget
left nothing for the daemon spawn, worker boot, channel connect and restart
(~4.5s measured on a quiet host, more in the sandbox). Raise it to 300s and say
what the extra 60s buys.

---------

Co-authored-by: 易良 <1204183885@qq.com>
This commit is contained in:
Shaojin Wen 2026-10-19 01:30:07 +08:00 • committed by GitHub
parent 6239c94ca0
commit ebb2ef7e9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -30,8 +30,16 @@ const CLI_BIN =
const TOKEN = 'multi-workspace-channel-test-token';
// The 10s production handshake budget is a desktop budget, not a shared-runner
// one: macOS E2E shards died on it in #11030 and reddened again in #11034.
// Match qwen-serve-routes.test.ts.
const ACP_INITIALIZE_TIMEOUT_MS = 60_000;
// This fixture was matched to qwen-serve-routes.test.ts until #14584. It also
// starts the nested Docker-sandbox ACP session that loads the linked channel
// extension (#10318), and that start is what stretches: #14584's run
// 39121969242 burned 139.9s across three attempts of the channel-less-boot
// scenario below, whose healthy sandbox:docker cost is 16.3s, while the same
// job's sandboxed CLI starts took 22-26s each. That scenario's per-test
// ceiling is 300s: two full budgets (240s) plus the scenario's fixed cost. It
// creates two tasks before the daemon restart and reloads both after, so two
// slow starts, not four, are what the budget has to absorb.
const ACP_INITIALIZE_TIMEOUT_MS = 120_000;
let daemon: ChildProcess | undefined;
let primaryServer: MockServerHandle | undefined;
@ -421,7 +429,7 @@ describe('qwen serve multi-workspace channel workers', () => {
await expect(
primaryServer.sendMessage('/session use review', bobTarget),
).resolves.toContain('Selected task "review"');
}, 60_000);
}, 300_000);
it('returns partial startup failures from control and daemon status', async () => {
testRoot = realpathSync(