feat(typesContext.tsx): add retry logic to getAll API call

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:
Gabriel Almeida 2023-05-19 10:07:13 -03:00
commit c93c4627d0

View file

@ -27,37 +27,71 @@ export function TypesProvider({ children }: { children: ReactNode }) {
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) => { async function getTypes(): Promise<void> {
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => { try {
acc[c] = result.data[curr][c]; const result = await getAll();
}); // Make sure to only update the state if the component is still mounted.
return acc; if (isMounted) {
}, {}) // Continue with your logic...
); setData(result.data);
// Set the types by reducing over the keys of the result data and updating the accumulator. setTemplates(
setTypes( Object.keys(result.data).reduce((acc, curr) => {
Object.keys(result.data).reduce((acc, curr) => { Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => { acc[c] = result.data[curr][c];
acc[c] = curr; });
// Add the base classes to the accumulator as well. return acc;
result.data[curr][c].base_classes?.forEach((b) => { }, {})
acc[b] = curr; );
}); // Set the types by reducing over the keys of the result data and updating the accumulator.
}); setTypes(
return acc; 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;
}, {})
);
}
// 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.");
}
}
} }
// Call the getTypes function.
getTypes(); // Start the initial interval.
}, [setTypes]); 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) { function deleteNode(idx: string) {
reactFlowInstance.setNodes( reactFlowInstance.setNodes(