diff --git a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx index 6966832db..fece752c7 100644 --- a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx +++ b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx @@ -315,9 +315,6 @@ export const MenuBar = ({}: {}): JSX.Element => { disabled={!isBuilding} onClick={(_) => { if (isBuilding) { - setIsBuilding(false); - revertBuiltStatusFromBuilding(); - setLockChat(false); window.stop(); } }} diff --git a/src/frontend/src/controllers/API/api.tsx b/src/frontend/src/controllers/API/api.tsx index 57aa2fb9c..787508836 100644 --- a/src/frontend/src/controllers/API/api.tsx +++ b/src/frontend/src/controllers/API/api.tsx @@ -208,6 +208,7 @@ export type StreamingRequestParams = { onData: (event: object) => Promise; body?: object; onError?: (statusCode: number) => void; + onNetworkError?: (error: Error) => void; }; async function performStreamingRequest({ @@ -216,6 +217,7 @@ async function performStreamingRequest({ onData, body, onError, + onNetworkError, }: StreamingRequestParams) { let headers = { "Content-Type": "application/json", @@ -248,35 +250,48 @@ async function performStreamingRequest({ if (response.body === null) { return; } - for await (const chunk of response.body) { - const decodedChunk = await textDecoder.decode(chunk); - let all = decodedChunk.split("\n\n"); - for (const string of all) { - if (string.endsWith("}")) { - const allString = current.join("") + string; - let data: object; - try { - data = JSON.parse(allString); - current = []; - } catch (e) { + try { + const reader = response.body.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + const decodedChunk = textDecoder.decode(value); + let all = decodedChunk.split("\n\n"); + for (const string of all) { + if (string.endsWith("}")) { + const allString = current.join("") + string; + let data: object; + try { + data = JSON.parse(allString); + current = []; + } catch (e) { + current.push(string); + continue; + } + const shouldContinue = await onData(data); + if (!shouldContinue) { + controller.abort(); + return; + } + } else { current.push(string); - continue; } - const shouldContinue = await onData(data); - if (!shouldContinue) { - controller.abort(); - return; - } - } else { - current.push(string); } } - } - if (current.length > 0) { - const allString = current.join(""); - if (allString) { - const data = JSON.parse(current.join("")); - await onData(data); + if (current.length > 0) { + const allString = current.join(""); + if (allString) { + const data = JSON.parse(current.join("")); + await onData(data); + } + } + } catch (e: any) { + if (onNetworkError) { + onNetworkError(e); + } else { + throw e; } } } diff --git a/src/frontend/src/stores/flowStore.ts b/src/frontend/src/stores/flowStore.ts index 94bac2eff..f30b3e7ed 100644 --- a/src/frontend/src/stores/flowStore.ts +++ b/src/frontend/src/stores/flowStore.ts @@ -642,6 +642,14 @@ const useFlowStore = create((set, get) => ({ get().setLockChat(false); }, onBuildUpdate: handleBuildUpdate, + onBuildStopped: () => { + get().setIsBuilding(false); + setErrorData({ + title: "Build stopped", + }); + get().revertBuiltStatusFromBuilding(); + get().setLockChat(false); + }, onBuildError: (title: string, list: string[], elementList) => { const idList = elementList .map((element) => element.id) diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts index 1a6a9f31c..c86165bcc 100644 --- a/src/frontend/src/utils/buildUtils.ts +++ b/src/frontend/src/utils/buildUtils.ts @@ -26,6 +26,7 @@ type BuildVerticesParams = { ) => void; // Replace any with the actual type if it's not any onBuildComplete?: (allNodesValid: boolean) => void; onBuildError?: (title, list, idList: VertexLayerElementType[]) => void; + onBuildStopped?: () => void; onBuildStart?: (idList: VertexLayerElementType[]) => void; onValidateNodes?: (nodes: string[]) => void; nodes?: Node[]; @@ -143,6 +144,7 @@ export async function buildFlowVertices({ onBuildUpdate, onBuildComplete, onBuildError, + onBuildStopped, onBuildStart, onValidateNodes, nodes, @@ -297,6 +299,8 @@ export async function buildFlowVertices({ } throw new Error("error in streaming request"); }, + // network error are likely caused by the window.stop() called in the stopBuild function + onNetworkError: onBuildStopped, }); }