fix: add direct event delivery option but keep polling as default (#7435)
* feat: add new event delivery method "direct" - Updated event_delivery options in ConfigResponse and Settings to include "direct". - Modified build_flow function to utilize settings_service for conditional event handling. - Improved flow processing by returning job_id or event responses based on delivery method. * feat: implement direct event delivery method on the frontend - Updated buildFlow function to include eventDelivery parameter, allowing for "direct" event delivery mode. - Modified NodeStatus and IOModal components to utilize the new eventDelivery setting. - Expanded flowStore and buildUtils to support event delivery options, improving flexibility in event handling. - Added "direct" option to event delivery types in enums for better configurability. - Updated tests to cover new event delivery modes. * fix: change default event delivery method to "polling" - Updated the default value of event_delivery in Settings from "direct" to "polling" to align with intended behavior. - Ensured documentation reflects the change in default settings for clarity on event delivery options. * Update src/frontend/src/controllers/API/api.tsx * Update src/frontend/src/utils/buildUtils.ts * Update src/frontend/src/utils/buildUtils.ts * Update src/frontend/src/utils/buildUtils.ts * feat: add event delivery validation for multi-worker environments - Introduced a new field validator for the `event_delivery` setting to enforce "direct" delivery when the number of workers exceeds one. - This change ensures compatibility with multi-worker setups, improving the robustness of event handling in the application. * feat: add warning for multi-worker event delivery - Added a warning log in the Settings class to notify users when a multi-worker environment is detected, indicating that "direct" event delivery will be used. This enhances visibility and understanding of event handling behavior in such setups. * refactor: remove "direct" from event delivery modes in tests - Updated the event delivery modes in the withEventDeliveryModes utility to exclude "direct", aligning with recent changes in event handling behavior. - This change simplifies the testing setup and ensures consistency with the current application logic. --------- Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
This commit is contained in:
parent
8b4cf7b1db
commit
d9ab4458ad
9 changed files with 104 additions and 10 deletions
|
|
@ -167,7 +167,11 @@ export default function NodeStatus({
|
|||
function handlePlayWShortcut() {
|
||||
if (buildStatus === BuildStatus.BUILDING || isBuilding || !selected) return;
|
||||
setValidationStatus(null);
|
||||
buildFlow({ stopNodeId: nodeId, stream: shouldStreamEvents() });
|
||||
buildFlow({
|
||||
stopNodeId: nodeId,
|
||||
stream: shouldStreamEvents(),
|
||||
eventDelivery: config.data?.event_delivery,
|
||||
});
|
||||
}
|
||||
|
||||
const play = useShortcutsStore((state) => state.play);
|
||||
|
|
@ -259,7 +263,11 @@ export default function NodeStatus({
|
|||
return;
|
||||
}
|
||||
if (buildStatus === BuildStatus.BUILDING || isBuilding) return;
|
||||
buildFlow({ stopNodeId: nodeId, stream: shouldStreamEvents() });
|
||||
buildFlow({
|
||||
stopNodeId: nodeId,
|
||||
stream: shouldStreamEvents(),
|
||||
eventDelivery: config.data?.event_delivery,
|
||||
});
|
||||
track("Flow Build - Clicked", { stopNodeId: nodeId });
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,4 +42,5 @@ export enum IOOutputTypes {
|
|||
export enum EventDeliveryType {
|
||||
STREAMING = "streaming",
|
||||
POLLING = "polling",
|
||||
DIRECT = "direct",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ export default function IOModal({
|
|||
silent: true,
|
||||
session: sessionId,
|
||||
stream: shouldStreamEvents(),
|
||||
eventDelivery: config.data?.event_delivery,
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import {
|
|||
FLOW_BUILD_SUCCESS_ALERT,
|
||||
MISSED_ERROR_ALERT,
|
||||
} from "../constants/alerts_constants";
|
||||
import { BuildStatus } from "../constants/enums";
|
||||
import { BuildStatus, EventDeliveryType } from "../constants/enums";
|
||||
import { LogsLogType, VertexBuildTypeAPI } from "../types/api";
|
||||
import { ChatInputType, ChatOutputType } from "../types/chat";
|
||||
import {
|
||||
|
|
@ -599,6 +599,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
silent,
|
||||
session,
|
||||
stream = true,
|
||||
eventDelivery = EventDeliveryType.STREAMING,
|
||||
}: {
|
||||
startNodeId?: string;
|
||||
stopNodeId?: string;
|
||||
|
|
@ -607,6 +608,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
silent?: boolean;
|
||||
session?: string;
|
||||
stream?: boolean;
|
||||
eventDelivery?: EventDeliveryType;
|
||||
}) => {
|
||||
const playgroundPage = get().playgroundPage;
|
||||
get().setIsBuilding(true);
|
||||
|
|
@ -834,6 +836,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
logBuilds: get().onFlowPage,
|
||||
playgroundPage,
|
||||
stream,
|
||||
eventDelivery,
|
||||
});
|
||||
get().setIsBuilding(false);
|
||||
get().revertBuiltStatusFromBuilding();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
ReactFlowInstance,
|
||||
Viewport,
|
||||
} from "@xyflow/react";
|
||||
import { BuildStatus } from "../../../constants/enums";
|
||||
import { BuildStatus, EventDeliveryType } from "../../../constants/enums";
|
||||
import { VertexBuildTypeAPI } from "../../api";
|
||||
import { ChatInputType, ChatOutputType } from "../../chat";
|
||||
import { FlowState } from "../../tabs";
|
||||
|
|
@ -150,6 +150,7 @@ export type FlowStoreType = {
|
|||
silent,
|
||||
session,
|
||||
stream,
|
||||
eventDelivery,
|
||||
}: {
|
||||
startNodeId?: string;
|
||||
stopNodeId?: string;
|
||||
|
|
@ -158,6 +159,7 @@ export type FlowStoreType = {
|
|||
silent?: boolean;
|
||||
session?: string;
|
||||
stream?: boolean;
|
||||
eventDelivery?: EventDeliveryType;
|
||||
}) => Promise<void>;
|
||||
getFlow: () => { nodes: Node[]; edges: EdgeType[]; viewport: Viewport };
|
||||
updateVerticesBuild: (
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { useMessagesStore } from "@/stores/messagesStore";
|
|||
import { Edge, Node } from "@xyflow/react";
|
||||
import { AxiosError } from "axios";
|
||||
import { flushSync } from "react-dom";
|
||||
import { BuildStatus } from "../constants/enums";
|
||||
import { BuildStatus, EventDeliveryType } from "../constants/enums";
|
||||
import { getVerticesOrder, postBuildVertex } from "../controllers/API";
|
||||
import useAlertStore from "../stores/alertStore";
|
||||
import useFlowStore from "../stores/flowStore";
|
||||
|
|
@ -41,6 +41,7 @@ type BuildVerticesParams = {
|
|||
session?: string;
|
||||
playgroundPage?: boolean;
|
||||
stream?: boolean;
|
||||
eventDelivery?: EventDeliveryType;
|
||||
};
|
||||
|
||||
function getInactiveVertexData(vertexId: string): VertexBuildTypeAPI {
|
||||
|
|
@ -139,7 +140,7 @@ export async function buildFlowVerticesWithFallback(
|
|||
) {
|
||||
logFlowLoad("Starting flow load");
|
||||
try {
|
||||
// Use shouldUsePolling() to determine stream mode
|
||||
// Use the event_delivery parameter directly
|
||||
return await buildFlowVertices({ ...params });
|
||||
} catch (e: any) {
|
||||
if (
|
||||
|
|
@ -241,6 +242,7 @@ export async function buildFlowVertices({
|
|||
session,
|
||||
playgroundPage,
|
||||
stream = true,
|
||||
eventDelivery,
|
||||
}: BuildVerticesParams) {
|
||||
const inputs = {};
|
||||
|
||||
|
|
@ -258,6 +260,11 @@ export async function buildFlowVertices({
|
|||
queryParams.append("log_builds", logBuilds.toString());
|
||||
}
|
||||
|
||||
// Add stream parameter when using direct event delivery
|
||||
if (eventDelivery === EventDeliveryType.DIRECT) {
|
||||
queryParams.append("stream", "true");
|
||||
}
|
||||
|
||||
if (queryParams.toString()) {
|
||||
buildUrl = `${buildUrl}?${queryParams.toString()}`;
|
||||
}
|
||||
|
|
@ -283,6 +290,57 @@ export async function buildFlowVertices({
|
|||
}
|
||||
|
||||
try {
|
||||
// If event_delivery is direct, we'll stream from the build endpoint directly
|
||||
if (eventDelivery === EventDeliveryType.DIRECT) {
|
||||
const buildController = new AbortController();
|
||||
buildController.signal.addEventListener("abort", () => {
|
||||
onBuildStopped && onBuildStopped();
|
||||
});
|
||||
useFlowStore.getState().setBuildController(buildController);
|
||||
|
||||
const buildResults: Array<boolean> = [];
|
||||
const verticesStartTimeMs: Map<string, number> = new Map();
|
||||
|
||||
return performStreamingRequest({
|
||||
method: "POST",
|
||||
url: buildUrl,
|
||||
body: postData,
|
||||
onData: async (event) => {
|
||||
const type = event["event"];
|
||||
const data = event["data"];
|
||||
return await onEvent(type, data, buildResults, verticesStartTimeMs, {
|
||||
onBuildStart,
|
||||
onBuildUpdate,
|
||||
onBuildComplete,
|
||||
onBuildError,
|
||||
onGetOrderSuccess,
|
||||
onValidateNodes,
|
||||
});
|
||||
},
|
||||
onError: (statusCode) => {
|
||||
if (statusCode === 404) {
|
||||
throw new Error("Flow not found");
|
||||
}
|
||||
throw new Error("Error processing build events");
|
||||
},
|
||||
onNetworkError: (error: Error) => {
|
||||
if (error.name === "AbortError") {
|
||||
onBuildStopped && onBuildStopped();
|
||||
return;
|
||||
}
|
||||
onBuildError!("Error Building Component", [
|
||||
"Network error. Please check the connection to the server.",
|
||||
]);
|
||||
},
|
||||
buildController,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
try {
|
||||
// Otherwise, use the existing two-step process (job_id + events endpoint)
|
||||
// First, start the build and get the job ID
|
||||
const buildResponse = await fetch(buildUrl, {
|
||||
method: "POST",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue