Bugfix - Retry Mechanism for Failed Requests in Loop (#808)

This pull request addresses an issue with the retry mechanism for failed
requests within a loop. The current implementation lacks proper handling
of failed requests, leading to potential data loss and inconsistent
behavior. This bugfix aims to improve the retry logic and ensure that
requests are appropriately retried when they fail within a loop.
This commit is contained in:
anovazzi1 2023-08-23 21:20:18 -03:00 committed by GitHub
commit cb5114b9b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 23 deletions

View file

@ -9,10 +9,16 @@ import ErrorAlert from "./alerts/error";
import NoticeAlert from "./alerts/notice";
import SuccessAlert from "./alerts/success";
import CrashErrorComponent from "./components/CrashErrorComponent";
import FetchErrorComponent from "./components/fetchErrorComponent";
import LoadingComponent from "./components/loadingComponent";
import {
FETCH_ERROR_DESCRIPION,
FETCH_ERROR_MESSAGE,
} from "./constants/constants";
import { alertContext } from "./contexts/alertContext";
import { locationContext } from "./contexts/locationContext";
import { TabsContext } from "./contexts/tabsContext";
import { typesContext } from "./contexts/typesContext";
import Router from "./routes";
export default function App() {
@ -38,6 +44,7 @@ export default function App() {
setSuccessOpen,
loading,
} = useContext(alertContext);
const { fetchError } = useContext(typesContext);
// Initialize state variable for the list of alerts
const [alertsList, setAlertsList] = useState<
@ -137,7 +144,14 @@ export default function App() {
>
{loading ? (
<div className="loading-page-panel">
<LoadingComponent remSize={50} />
{fetchError ? (
<FetchErrorComponent
description={FETCH_ERROR_DESCRIPION}
message={FETCH_ERROR_MESSAGE}
></FetchErrorComponent>
) : (
<LoadingComponent remSize={50} />
)}
</div>
) : (
<>

View file

@ -0,0 +1,16 @@
import { fetchErrorComponentType } from "../../types/components";
import IconComponent from "../genericIconComponent";
export default function FetchErrorComponent({
message,
description,
}: fetchErrorComponentType) {
return (
<div role="status" className="m-auto flex flex-col items-center">
<IconComponent className={`h-16 w-16`} name="Unplug"></IconComponent>
<br></br>
<span className="text-lg text-almost-medium-blue">{message}</span>
<span className="text-lg text-almost-medium-blue">{description}</span>
</div>
);
}

View file

@ -7,5 +7,11 @@ export default function IconComponent({
iconColor,
}: IconComponentProps): JSX.Element {
const TargetIcon = nodeIconsLucide[name] ?? nodeIconsLucide["unknown"];
return <TargetIcon className={className} style={{ color: iconColor }} />;
return (
<TargetIcon
className={className}
style={{ color: iconColor }}
stroke-width={1.5}
/>
);
}

View file

@ -1,6 +1,4 @@
type LoadingComponentProps = {
remSize: number;
};
import { LoadingComponentProps } from "../../types/components";
export default function LoadingComponent({ remSize }: LoadingComponentProps) {
return (

View file

@ -511,3 +511,7 @@ export const URL_EXCLUDED_FROM_ERROR_RETRIES = [
];
export const skipNodeUpdate = ["CustomComponent"];
export const FETCH_ERROR_MESSAGE = "Couldn't establish a connection.";
export const FETCH_ERROR_DESCRIPION =
"Check if everything is working properly and try again.";

View file

@ -6,7 +6,7 @@ import {
useState,
} from "react";
import { Node } from "reactflow";
import { getAll } from "../controllers/API";
import { getAll, getHealth } from "../controllers/API";
import { APIKindType } from "../types/api";
import { typesContextType } from "../types/typesContext";
import { alertContext } from "./alertContext";
@ -23,6 +23,8 @@ const initialValue: typesContextType = {
setTemplates: () => {},
data: {},
setData: () => {},
setFetchError: () => {},
fetchError: false,
};
export const typesContext = createContext<typesContextType>(initialValue);
@ -32,14 +34,10 @@ export function TypesProvider({ children }: { children: ReactNode }) {
const [reactFlowInstance, setReactFlowInstance] = useState(null);
const [templates, setTemplates] = useState({});
const [data, setData] = useState({});
const [fetchError, setFetchError] = useState(false);
const { setLoading } = useContext(alertContext);
useEffect(() => {
let delay = 1000; // Start delay of 1 second
let intervalId = null;
let retryCount = 0; // Count of retry attempts
const maxRetryCount = 5; // Max retry attempts
// We will keep a flag to handle the case where the component is unmounted before the API call resolves.
let isMounted = true;
@ -47,7 +45,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
try {
const result = await getAll();
// Make sure to only update the state if the component is still mounted.
if (isMounted) {
if (isMounted && result?.status === 200) {
setLoading(false);
setData(result.data);
setTemplates(
@ -77,22 +75,15 @@ export function TypesProvider({ children }: { children: ReactNode }) {
}, {})
);
}
// Clear the interval if successful.
clearInterval(intervalId);
} catch (error) {
console.error("An error has occurred while fetching types.");
await getHealth().catch((e) => {
setFetchError(true);
});
}
}
// Start the initial interval.
intervalId = setInterval(getTypes, delay);
return () => {
// This will clear the interval when the component unmounts, or when the dependencies of the useEffect hook change.
clearInterval(intervalId);
// Indicate that the component has been unmounted.
isMounted = false;
};
getTypes();
}, []);
function deleteNode(idx: string) {
@ -117,6 +108,8 @@ export function TypesProvider({ children }: { children: ReactNode }) {
templates,
data,
setData,
fetchError,
setFetchError,
}}
>
{children}

View file

@ -171,3 +171,11 @@ export type IconComponentProps = {
export interface languageMap {
[key: string]: string | undefined;
}
export type fetchErrorComponentType = {
message: string;
description: string;
};
export type LoadingComponentProps = {
remSize: number;
};

View file

@ -15,4 +15,6 @@ export type typesContextType = {
setTemplates: (newState: {}) => void;
data: typeof data;
setData: (newState: {}) => void;
fetchError: boolean;
setFetchError: (newState: boolean) => void;
};

View file

@ -56,6 +56,7 @@ import {
TerminalSquare,
Trash2,
Undo,
Unplug,
Upload,
Users2,
Variable,
@ -275,4 +276,5 @@ export const nodeIconsLucide = {
Upload,
MessageSquare,
MoreHorizontal,
Unplug,
};