fix: implemented build stop functionality on polling, call cancel endpoint on build cancel (#6815)

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
Lucas Oliveira 2025-02-25 19:11:23 -03:00 • committed by GitHub
commit 0134485d5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 226 additions and 13 deletions

View file

@ -237,6 +237,7 @@ export type StreamingRequestParams = {
body?: object;
onError?: (statusCode: number) => void;
onNetworkError?: (error: Error) => void;
buildController: AbortController;
};
async function performStreamingRequest({
@ -246,18 +247,18 @@ async function performStreamingRequest({
body,
onError,
onNetworkError,
buildController,
}: StreamingRequestParams) {
let headers = {
"Content-Type": "application/json",
// this flag is fundamental to ensure server stops tasks when client disconnects
Connection: "close",
};
const controller = new AbortController();
useFlowStore.getState().setBuildController(controller);
const params = {
method: method,
headers: headers,
signal: controller.signal,
signal: buildController.signal,
};
if (body) {
params["body"] = JSON.stringify(body);
@ -298,7 +299,7 @@ async function performStreamingRequest({
}
const shouldContinue = await onData(data);
if (!shouldContinue) {
controller.abort();
buildController.abort();
return;
}
} else {

View file

@ -1,3 +1,4 @@
import { MISSED_ERROR_ALERT } from "@/constants/alerts_constants";
import {
BASE_URL_API,
POLLING_INTERVAL,
@ -93,7 +94,7 @@ export async function updateVerticesOrder(
);
} catch (error: any) {
setErrorData({
title: "Oops! Looks like you missed something",
title: MISSED_ERROR_ALERT,
list: [error.response?.data?.detail ?? "Unknown Error"],
});
useFlowStore.getState().setIsBuilding(false);
@ -161,6 +162,7 @@ async function pollBuildEvents(
onGetOrderSuccess?: () => void;
onValidateNodes?: (nodes: string[]) => void;
},
abortController: AbortController,
): Promise<void> {
let isDone = false;
while (!isDone) {
@ -169,6 +171,7 @@ async function pollBuildEvents(
headers: {
"Content-Type": "application/json",
},
signal: abortController.signal, // Add abort signal to fetch
});
if (!response.ok) {
@ -184,13 +187,17 @@ async function pollBuildEvents(
// Process the event
const event = JSON.parse(data.event);
await onEvent(
const result = await onEvent(
event.event,
event.data,
buildResults,
verticesStartTimeMs,
callbacks,
);
if (!result) {
isDone = true;
abortController.abort();
}
// Check if this was the end event or if we got a null value
if (event.event === "end" || data.event === null) {
@ -278,6 +285,24 @@ export async function buildFlowVertices({
const { job_id } = await buildResponse.json();
const cancelBuildUrl = `${BASE_URL_API}build/${job_id}/cancel`;
// Get the buildController from flowStore
const buildController = new AbortController();
buildController.signal.addEventListener("abort", () => {
try {
fetch(cancelBuildUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
} catch (error) {
console.error("Error canceling build:", error);
}
});
useFlowStore.getState().setBuildController(buildController);
// Then stream the events
const eventsUrl = `${BASE_URL_API}build/${job_id}/events`;
const buildResults: Array<boolean> = [];
@ -314,6 +339,7 @@ export async function buildFlowVertices({
"Network error. Please check the connection to the server.",
]);
},
buildController,
});
} else {
const callbacks = {
@ -329,10 +355,15 @@ export async function buildFlowVertices({
buildResults,
verticesStartTimeMs,
callbacks,
buildController,
);
}
} catch (error) {
} catch (error: unknown) {
console.error("Build process error:", error);
if (error instanceof Error && error.name === "AbortError") {
onBuildStopped && onBuildStopped();
return;
}
onBuildError!("Error Building Flow", [
(error as Error).message || "An unexpected error occurred",
]);