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:
commit
5090cdae7e
1 changed files with 104 additions and 71 deletions
|
|
@ -7,83 +7,116 @@ import { APIKindType } from "../types/api";
|
|||
//context to share types adn functions from nodes to flow
|
||||
|
||||
const initialValue: typesContextType = {
|
||||
reactFlowInstance: null,
|
||||
setReactFlowInstance: () => {},
|
||||
deleteNode: () => {},
|
||||
types: {},
|
||||
setTypes: () => {},
|
||||
templates: {},
|
||||
setTemplates: () => {},
|
||||
data: {},
|
||||
setData: () => {},
|
||||
reactFlowInstance: null,
|
||||
setReactFlowInstance: () => {},
|
||||
deleteNode: () => {},
|
||||
types: {},
|
||||
setTypes: () => {},
|
||||
templates: {},
|
||||
setTemplates: () => {},
|
||||
data: {},
|
||||
setData: () => {},
|
||||
};
|
||||
|
||||
export const typesContext = createContext<typesContextType>(initialValue);
|
||||
|
||||
export function TypesProvider({ children }: { children: ReactNode }) {
|
||||
const [types, setTypes] = useState({});
|
||||
const [reactFlowInstance, setReactFlowInstance] = useState(null);
|
||||
const [templates, setTemplates] = useState({});
|
||||
const [data, setData] = useState({});
|
||||
const [types, setTypes] = useState({});
|
||||
const [reactFlowInstance, setReactFlowInstance] = useState(null);
|
||||
const [templates, setTemplates] = useState({});
|
||||
const [data, setData] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
async function getTypes(): Promise<void> {
|
||||
// Make an asynchronous API call to retrieve all data.
|
||||
let result = await getAll();
|
||||
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
|
||||
|
||||
// Update the state of the component with the retrieved data.
|
||||
setData(result.data);
|
||||
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]);
|
||||
// We will keep a flag to handle the case where the component is unmounted before the API call resolves.
|
||||
let isMounted = true;
|
||||
|
||||
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>
|
||||
);
|
||||
async function getTypes(): Promise<void> {
|
||||
try {
|
||||
const result = await getAll();
|
||||
// Make sure to only update the state if the component is still mounted.
|
||||
if (isMounted) {
|
||||
setData(result.data);
|
||||
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;
|
||||
}, {})
|
||||
);
|
||||
}
|
||||
// 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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue