Skip to content

Commit 26869ed

Browse files
fix(local): detect upstream disconnect in --quiet attach mode
Previously, --quiet mode waited only for SIGINT/SIGTERM and would hang indefinitely if the upstream server shut down. Now it consumes the SSE stream (draining chunks without parsing) so the for-await loop exits naturally on disconnect.
1 parent 5c32850 commit 26869ed

1 file changed

Lines changed: 19 additions & 17 deletions

File tree

src/commands/local.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,8 @@ function feedSSELine(
713713
async function consumeSSE(
714714
url: string,
715715
activeFilters: ReadonlySet<FilterValue>,
716-
signal: AbortSignal
716+
signal: AbortSignal,
717+
quiet = false
717718
): Promise<void> {
718719
const res = await fetch(`${url}/stream`, {
719720
headers: { Accept: "text/event-stream" },
@@ -723,6 +724,15 @@ async function consumeSSE(
723724
return;
724725
}
725726

727+
// In quiet mode we still consume the stream to detect disconnection,
728+
// but skip parsing/formatting entirely.
729+
if (quiet) {
730+
for await (const _chunk of res.body) {
731+
// drain
732+
}
733+
return;
734+
}
735+
726736
const decoder = new TextDecoder();
727737
const state: SSEParserState = { eventType: "", dataLines: [] };
728738
const onEvent = (type: string, data: string) => {
@@ -842,23 +852,15 @@ export const localCommand = buildCommand({
842852
process.once("SIGINT", stop);
843853
process.once("SIGTERM", stop);
844854

845-
if (flags.quiet) {
846-
await new Promise<void>((resolve) => {
847-
if (ac.signal.aborted) {
848-
resolve();
849-
return;
855+
// Connect to the SSE stream even in quiet mode so we detect when
856+
// the upstream server disconnects (the for-await loop exits).
857+
await consumeSSE(url, activeFilters, ac.signal, flags.quiet).catch(
858+
(err: unknown) => {
859+
if (!(err instanceof DOMException && err.name === "AbortError")) {
860+
throw err;
850861
}
851-
ac.signal.addEventListener("abort", () => resolve());
852-
});
853-
} else {
854-
await consumeSSE(url, activeFilters, ac.signal).catch(
855-
(err: unknown) => {
856-
if (!(err instanceof DOMException && err.name === "AbortError")) {
857-
throw err;
858-
}
859-
}
860-
);
861-
}
862+
}
863+
);
862864
logger.log("Disconnected.");
863865
return;
864866
}

0 commit comments

Comments
 (0)