fix(test-servers): address review on the cancellation showcase
- `slow_task` sleeps through a helper that removes both listeners on
whichever outcome wins and returns early on an already-aborted signal.
`{ once: true }` detaches on the event firing, not on the waiter losing
interest, so the old loop left one listener per second attached and a
60s run tripped MaxListenersExceededWarning.
- Report the outcome on stderr. A successful cancel closes the stream the
result would travel on, so the tool's return value is undeliverable by
construction — the README now points at the server's terminal rather
than at a result panel that cannot show it.
- Drop a double cast the file's own next hunk shows is unnecessary, and a
floating observer promise whose assertion was false anyway: `postSend`
rethrows before awaiting the SSE wait, so the send rejects on abort
whether or not that wait was cancelled.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
85c5206895
commit
56d3c04643
1 changed files with 67 additions and 33 deletions
|
|
@ -579,7 +579,7 @@ describe("RemoteClientTransport", () => {
|
|||
it("advertises hasPerRequestStream only for streamable-http", () => {
|
||||
const forType = (c: MCPServerConfig) =>
|
||||
new RemoteClientTransport(
|
||||
{ baseUrl, fetchFn: vi.fn() as unknown as typeof fetch },
|
||||
{ baseUrl, fetchFn: vi.fn<typeof fetch>() },
|
||||
c,
|
||||
).hasPerRequestStream;
|
||||
|
||||
|
|
@ -640,7 +640,7 @@ describe("RemoteClientTransport", () => {
|
|||
await transport.close();
|
||||
});
|
||||
|
||||
it("aborting the requestSignal rejects the in-flight send and releases its response wait", async () => {
|
||||
it("aborting the requestSignal rejects the in-flight send", async () => {
|
||||
let sse = createPushableSseStream();
|
||||
const fetchFn = vi
|
||||
.fn<typeof fetch>()
|
||||
|
|
@ -675,15 +675,13 @@ describe("RemoteClientTransport", () => {
|
|||
{ jsonrpc: "2.0", id: 7, method: "tools/call" },
|
||||
{ requestSignal: controller.signal },
|
||||
);
|
||||
const settled = vi.fn();
|
||||
void sent.then(settled, settled);
|
||||
|
||||
controller.abort();
|
||||
// The backend never answers an aborted send, so the rejection has to come
|
||||
// from the fetch itself. `postSend` already cancels the SSE response wait
|
||||
// it registered for this id on that path (its catch does, unchanged by
|
||||
// #2140) — so the send surfaces the abort rather than the wait's timeout.
|
||||
await expect(sent).rejects.toThrow(/Aborted/);
|
||||
// The response wait registered for id 7 must have been cancelled too —
|
||||
// otherwise this send would hang past the abort waiting for a JSON-RPC
|
||||
// response the aborted request can never produce.
|
||||
expect(settled).toHaveBeenCalledTimes(1);
|
||||
|
||||
await transport.close();
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue