fix: display errors when webhook background tasks fail (#7572)

* 📝 (base.py): improve naming convention for task names in Graph class
🔧 (base.py): add error logging functionality in _execute_tasks method
🔧 (utils.py): update data parameter type in log_vertex_build function
🔧 (index.tsx): remove unused setCurrentFlow function call in StoreCardComponent
🔧 (use-get-builds-polling-mutation.ts): add error handling and display logic for build failures
🔧 (flowSidebarComponent/index.tsx): make showLegacy prop optional in FlowSidebarComponentProps interface
🔧 (index.tsx): remove commented out code related to branding in FlowPage component

* [autofix.ci] apply automated fixes

* fix: update URL construction in CopyFieldAreaComponent to handle undefined endpointName

- Modified the URL construction logic to use currentFlow.id when endpointName is not provided, ensuring a valid URL is always generated.

* 🔧 (base.py): add error logging method for vertex build failures

- Introduced `_log_vertex_build_from_exception` method to handle and log exceptions during vertex building, improving error reporting and output structure.
- Updated `_execute_tasks` method to utilize the new logging method for better exception handling.

* 🐛 (use-get-builds-polling-mutation.ts): fix error display count to only show errors once per build failure instead of multiple times

* 📝 (embedding_model.py): improve formatting of the info message for the 'dimensions' input to enhance readability and clarity

* [autofix.ci] apply automated fixes

* fix: add webhook component handling in task execution

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
Cristhian Zanforlin Lousa 2025-04-24 19:18:49 -03:00 committed by GitHub
commit eed7dee8bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 114 additions and 62 deletions

View file

@ -196,45 +196,6 @@ export default function StoreCardComponent({
<CardFooter>
<div className="z-50 flex w-full items-center justify-between gap-2">
<div className="flex w-full flex-wrap items-end justify-end gap-2">
{/* {playground && (
<Button
disabled={loadingPlayground || !authorized}
key={data.id}
tabIndex={-1}
variant="outline"
size="sm"
className="z-50 gap-2 whitespace-nowrap"
data-testid={"playground-flow-button-" + data.id}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setLoadingPlayground(true);
getFlowData().then((res) => {
if (!hasPlayground(res)) {
setErrorData({
title: "Error",
list: ["This flow doesn't have a playground."],
});
setLoadingPlayground(false);
return;
}
setCurrentFlow(res);
setOpenPlayground(true);
setLoadingPlayground(false);
});
}}
>
{!loadingPlayground ? (
<IconComponent
name="BotMessageSquareIcon"
className="h-4 w-4 select-none"
/>
) : (
<Loading className="h-4 w-4 text-medium-indigo" />
)}
Playground
</Button>
)} */}
<div className="flex gap-0.5">
<ShadTooltip
content={authorized ? "Like" : "Please review your API key."}

View file

@ -62,7 +62,6 @@ export default function CopyFieldAreaComponent({
const [isFocused, setIsFocused] = useState(false);
const [isCopied, setIsCopied] = useState(false);
const isValueToReplace = value === BACKEND_URL || value === MCP_SSE_VALUE;
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const currentFlow = useFlowStore((state) => state.currentFlow);
const endpointName = currentFlow?.endpoint_name ?? "";

View file

@ -1,3 +1,4 @@
import useAlertStore from "@/stores/alertStore";
import useFlowStore from "@/stores/flowStore";
import { useUtilityStore } from "@/stores/utilityStore";
import { useMutationFunctionType } from "@/types/api";
@ -7,6 +8,9 @@ import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";
const ERROR_DISPLAY_INTERVAL = 10000;
const ERROR_DISPLAY_COUNT = 1;
interface PollingItem {
interval: NodeJS.Timeout;
timestamp: number;
@ -96,6 +100,10 @@ export const useGetBuildsMutation: useMutationFunctionType<
const flowIdRef = useRef<string | null>(null);
const requestInProgressRef = useRef<Record<string, boolean>>({});
const errorDisplayCountRef = useRef<number>(0);
const timeoutIdsRef = useRef<number[]>([]);
const setErrorData = useAlertStore((state) => state.setErrorData);
const getBuildsFn = async (
payload: IGetBuilds,
@ -115,6 +123,24 @@ export const useGetBuildsMutation: useMutationFunctionType<
if (Object.keys(flowPool).length > 0) {
setFlowPool(flowPool);
}
// Check for errors only if we haven't displayed them yet
if (errorDisplayCountRef.current === 0) {
Object.keys(flowPool).forEach((key) => {
const nodeBuild = flowPool[key];
if (nodeBuild.length > 0 && nodeBuild[0]?.valid === false) {
const errorMessage = nodeBuild?.[0]?.params || "Unknown error";
if (errorMessage) {
setErrorData({
title: "Last build failed",
list: [errorMessage],
});
errorDisplayCountRef.current = 1;
}
}
});
}
return;
}
@ -145,9 +171,9 @@ export const useGetBuildsMutation: useMutationFunctionType<
const timestamp = Date.now();
const pollCallback = async () => {
const data = await getBuildsFn(payload);
payload.onSuccess?.(data);
payload.onSuccess?.(data!);
if (payload.stopPollingOn?.(data)) {
if (payload.stopPollingOn?.(data!)) {
PollingManager.stopPoll(payload.flowId);
}
};
@ -164,8 +190,8 @@ export const useGetBuildsMutation: useMutationFunctionType<
PollingManager.enqueuePolling(payload.flowId, pollingItem);
return getBuildsFn(payload).then((data) => {
payload.onSuccess?.(data);
if (payload.stopPollingOn?.(data)) {
payload.onSuccess?.(data!);
if (payload.stopPollingOn?.(data!)) {
PollingManager.stopPoll(payload.flowId);
}
});
@ -176,6 +202,13 @@ export const useGetBuildsMutation: useMutationFunctionType<
if (flowIdRef.current) {
PollingManager.stopPoll(flowIdRef.current);
}
// Clear all timeouts
timeoutIdsRef.current.forEach((timeoutId) => {
clearTimeout(timeoutId);
});
timeoutIdsRef.current = [];
// Reset error display count when component unmounts
errorDisplayCountRef.current = 0;
};
}, []);

View file

@ -172,17 +172,6 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
</SidebarProvider>
</div>
)}
{/* {ENABLE_BRANDING && version && (
<a
target={"_blank"}
href="https://medium.com/logspace/langflow-datastax-better-together-1b7462cebc4d"
className="langflow-page-icon"
>
<div className="mt-1">Langflow 🤝 DataStax</div>
<div className={version ? "mt-2" : "mt-1"}> v{version}</div>
</a>
)} */}
</div>
{blocker.state === "blocked" && (
<>