Retry_get_all (#324)

This commit adds retry logic to the getAll API call in the TypesProvider
component. The retry logic will attempt to make the API call up to 5
times with an increasing delay between each attempt. If the API call is
successful, the state of the component will be updated with the
retrieved data. If the component is unmounted before the API call
resolves, the state will not be updated.
This commit is contained in:
anovazzi1 2023-05-22 00:24:10 -03:00 • committed by GitHub
commit 5090cdae7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -7,83 +7,116 @@ import { APIKindType } from "../types/api";
//context to share types adn functions from nodes to flow //context to share types adn functions from nodes to flow
const initialValue: typesContextType = { const initialValue: typesContextType = {
reactFlowInstance: null, reactFlowInstance: null,
setReactFlowInstance: () => {}, setReactFlowInstance: () => {},
deleteNode: () => {}, deleteNode: () => {},
types: {}, types: {},
setTypes: () => {}, setTypes: () => {},
templates: {}, templates: {},
setTemplates: () => {}, setTemplates: () => {},
data: {}, data: {},
setData: () => {}, setData: () => {},
}; };
export const typesContext = createContext<typesContextType>(initialValue); export const typesContext = createContext<typesContextType>(initialValue);
export function TypesProvider({ children }: { children: ReactNode }) { export function TypesProvider({ children }: { children: ReactNode }) {
const [types, setTypes] = useState({}); const [types, setTypes] = useState({});
const [reactFlowInstance, setReactFlowInstance] = useState(null); const [reactFlowInstance, setReactFlowInstance] = useState(null);
const [templates, setTemplates] = useState({}); const [templates, setTemplates] = useState({});
const [data, setData] = useState({}); const [data, setData] = useState({});
useEffect(() => { useEffect(() => {
async function getTypes(): Promise<void> { let delay = 1000; // Start delay of 1 second
// Make an asynchronous API call to retrieve all data. let intervalId = null;
let result = await getAll(); let retryCount = 0; // Count of retry attempts
const maxRetryCount = 5; // Max retry attempts
// Update the state of the component with the retrieved data. // We will keep a flag to handle the case where the component is unmounted before the API call resolves.
setData(result.data); let isMounted = true;
setTemplates(
Object.keys(result.data).reduce((acc, curr) => {
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
acc[c] = result.data[curr][c];
});
return acc;
}, {})
);
// Set the types by reducing over the keys of the result data and updating the accumulator.
setTypes(
Object.keys(result.data).reduce((acc, curr) => {
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
acc[c] = curr;
// Add the base classes to the accumulator as well.
result.data[curr][c].base_classes?.forEach((b) => {
acc[b] = curr;
});
});
return acc;
}, {})
);
}
// Call the getTypes function.
getTypes();
}, [setTypes]);
function deleteNode(idx: string) { async function getTypes(): Promise<void> {
reactFlowInstance.setNodes( try {
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx) const result = await getAll();
); // Make sure to only update the state if the component is still mounted.
reactFlowInstance.setEdges( if (isMounted) {
reactFlowInstance setData(result.data);
.getEdges() setTemplates(
.filter((ns) => ns.source !== idx && ns.target !== idx) Object.keys(result.data).reduce((acc, curr) => {
); Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
} acc[c] = result.data[curr][c];
return ( });
<typesContext.Provider return acc;
value={{ }, {})
types, );
setTypes, // Set the types by reducing over the keys of the result data and updating the accumulator.
reactFlowInstance, setTypes(
setReactFlowInstance, Object.keys(result.data).reduce((acc, curr) => {
deleteNode, Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
setTemplates, acc[c] = curr;
templates, // Add the base classes to the accumulator as well.
data, result.data[curr][c].base_classes?.forEach((b) => {
setData, acc[b] = curr;
}} });
> });
{children} return acc;
</typesContext.Provider> }, {})
); );
}
// Clear the interval if successful.
clearInterval(intervalId);
} catch (error) {
retryCount++;
// On error, double the delay for the next attempt up to a maximum.
delay = Math.min(30000, delay * 2);
// Log errors but don't do anything else - the function will try again on the next interval.
console.error(error);
// Clear the old interval and start a new one with the new delay.
if (retryCount <= maxRetryCount) {
clearInterval(intervalId);
intervalId = setInterval(getTypes, delay);
} else {
console.error("Max retry attempts reached. Stopping retries.");
}
}
}
// 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;
};
}, []);
function deleteNode(idx: string) {
reactFlowInstance.setNodes(
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx)
);
reactFlowInstance.setEdges(
reactFlowInstance
.getEdges()
.filter((ns) => ns.source !== idx && ns.target !== idx)
);
}
return (
<typesContext.Provider
value={{
types,
setTypes,
reactFlowInstance,
setReactFlowInstance,
deleteNode,
setTemplates,
templates,
data,
setData,
}}
>
{children}
</typesContext.Provider>
);
} }