Skip to content

Commit 228367d

Browse files
committed
Neutral wording for the session startup regression test
1 parent 063b0e8 commit 228367d

1 file changed

Lines changed: 16 additions & 22 deletions

File tree

e2e/cloud/repro-transport-brick.test.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,23 @@
1-
// Cloud: regression test for the CONFIRMED production "session brick" failure (observed
2-
// 3/3 against executor.sh prod on 2026-07-04). The recipe:
1+
// Cloud: regression test for a session-DO startup race.
32
//
4-
// 1. Open an MCP session (real SDK client init mcp-session-id), make a
5-
// call, close the client.
6-
// 2. Idle PAST the session timeout so the DO's alarm runs disposeIdleRuntime
3+
// 1. Open an MCP session (real SDK client init, capture mcp-session-id),
4+
// make a call, close the client.
5+
// 2. Idle past the session timeout so the DO's alarm runs disposeIdleRuntime
76
// (runtime torn down, `initialized = false`, transport cleared).
8-
// 3. Fire an SSE GET (listen stream) and a POST (tools/list) CONCURRENTLY on
7+
// 3. Fire an SSE GET (listen stream) and a POST (tools/list) concurrently on
98
// the same session id.
10-
// 4. The session must survive: the concurrent pair and follow-up calls should
11-
// succeed instead of leaving the DO permanently bricked.
9+
// 4. The session must survive: the concurrent pair and follow-up calls
10+
// should succeed.
1211
//
13-
// Mechanism: after
14-
// idle-dispose, a request carrying a session id runs
15-
// validateMcpSessionOwner → onStart → server.connect(_transport). The SDK's
16-
// own serve() streaming handler then does its own agent.fetch(Upgrade:websocket),
17-
// waking the DO, whose Agent base ALSO drives onStart → a SECOND
18-
// server.connect on a server whose _transport is already set →
19-
// "Already connected to a transport. Call close() before connecting to a new
20-
// transport." Two concurrent GET+POST restores interleave and collide.
21-
//
22-
// Observed locally (workerd, MCP_SESSION_TIMEOUT_MS=3000): the concurrent pair
23-
// itself usually answers 200/200 — one restore wins the race — but the race
24-
// leaves the DO's McpServer half-connected, and EVERY subsequent request 500s
25-
// with the "Already connected" error. Same permanent grave as prod; prod's
26-
// slower timing surfaced the 500 on the pair itself.
12+
// Mechanism guarded against: a request carrying a session id runs
13+
// validateMcpSessionOwner, which restores via onStart when the runtime is
14+
// disposed. The SDK's serve() streaming handler separately wakes the DO
15+
// through agent.fetch, and the Agent base also drives onStart. Without
16+
// serialization across both entry paths, two onStart calls interleave and the
17+
// second server.connect throws "Already connected to a transport", after
18+
// which every request on the session fails the same way. The concurrent pair
19+
// itself can answer 200/200 (one restore wins the race), so the assertions
20+
// cover the follow-up calls, which is where the failure persists.
2721
//
2822
import { writeFileSync } from "node:fs";
2923
import { join } from "node:path";

0 commit comments

Comments
 (0)