feat: improve getHealth logic (#2537)
* create get health custom hook * refactor getHealth to use useQuery get * fix: getHealth in App.tsx * [autofix.ci] apply automated fixes * refactor: update API endpoint in useGetHealthQuery * chore: use new get_helth body * [autofix.ci] apply automated fixes * update interfaces names * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Cristhian Zanforlin Lousa <72977554+Cristhianzl@users.noreply.github.com>
This commit is contained in:
parent
71e3ed92d8
commit
6160f70011
4 changed files with 69 additions and 69 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { ErrorBoundary } from "react-error-boundary";
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
@ -13,7 +12,8 @@ import {
|
||||||
FETCH_ERROR_MESSAGE,
|
FETCH_ERROR_MESSAGE,
|
||||||
} from "./constants/constants";
|
} from "./constants/constants";
|
||||||
import { AuthContext } from "./contexts/authContext";
|
import { AuthContext } from "./contexts/authContext";
|
||||||
import { autoLogin, getGlobalVariables, getHealth } from "./controllers/API";
|
import { autoLogin } from "./controllers/API";
|
||||||
|
import { useGetHealthQuery } from "./controllers/API/queries/health";
|
||||||
import { useGetVersionQuery } from "./controllers/API/queries/version";
|
import { useGetVersionQuery } from "./controllers/API/queries/version";
|
||||||
import { setupAxiosDefaults } from "./controllers/API/utils";
|
import { setupAxiosDefaults } from "./controllers/API/utils";
|
||||||
import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path";
|
import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path";
|
||||||
|
|
@ -25,21 +25,22 @@ import useFlowsManagerStore from "./stores/flowsManagerStore";
|
||||||
import { useFolderStore } from "./stores/foldersStore";
|
import { useFolderStore } from "./stores/foldersStore";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const queryClient = new QueryClient();
|
|
||||||
|
|
||||||
useTrackLastVisitedPath();
|
useTrackLastVisitedPath();
|
||||||
const [fetchError, setFetchError] = useState(false);
|
|
||||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||||
const { isAuthenticated, login, setUserData, setAutoLogin, getUser } =
|
const { isAuthenticated, login, setUserData, setAutoLogin, getUser } =
|
||||||
useContext(AuthContext);
|
useContext(AuthContext);
|
||||||
const setLoading = useAlertStore((state) => state.setLoading);
|
const setLoading = useAlertStore((state) => state.setLoading);
|
||||||
const refreshStars = useDarkStore((state) => state.refreshStars);
|
const refreshStars = useDarkStore((state) => state.refreshStars);
|
||||||
const navigate = useNavigate();
|
|
||||||
const dark = useDarkStore((state) => state.dark);
|
const dark = useDarkStore((state) => state.dark);
|
||||||
|
|
||||||
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
|
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
|
||||||
|
|
||||||
const [isLoadingHealth, setIsLoadingHealth] = useState(false);
|
const {
|
||||||
|
data: healthData,
|
||||||
|
isFetching: fetchingHealth,
|
||||||
|
isError: isErrorHealth,
|
||||||
|
refetch,
|
||||||
|
} = useGetHealthQuery();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!dark) {
|
if (!dark) {
|
||||||
document.getElementById("body")!.classList.remove("dark");
|
document.getElementById("body")!.classList.remove("dark");
|
||||||
|
|
@ -102,49 +103,6 @@ export default function App() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
checkApplicationHealth();
|
|
||||||
// Timer to call getHealth every 5 seconds
|
|
||||||
const timer = setInterval(() => {
|
|
||||||
getHealth()
|
|
||||||
.then(() => {
|
|
||||||
onHealthCheck();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setFetchError(true);
|
|
||||||
});
|
|
||||||
}, 20000); // 20 seconds
|
|
||||||
|
|
||||||
// Clean up the timer on component unmount
|
|
||||||
return () => {
|
|
||||||
clearInterval(timer);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const checkApplicationHealth = () => {
|
|
||||||
setIsLoadingHealth(true);
|
|
||||||
getHealth()
|
|
||||||
.then(() => {
|
|
||||||
onHealthCheck();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setFetchError(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
setIsLoadingHealth(false);
|
|
||||||
}, 2000);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onHealthCheck = () => {
|
|
||||||
setFetchError(false);
|
|
||||||
//This condition is necessary to avoid infinite loop on starter page when the application is not healthy
|
|
||||||
if (isLoading === true && window.location.pathname === "/") {
|
|
||||||
navigate("/all");
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isLoadingApplication = isLoading || isLoadingFolders;
|
const isLoadingApplication = isLoading || isLoadingFolders;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -161,11 +119,16 @@ export default function App() {
|
||||||
<FetchErrorComponent
|
<FetchErrorComponent
|
||||||
description={FETCH_ERROR_DESCRIPION}
|
description={FETCH_ERROR_DESCRIPION}
|
||||||
message={FETCH_ERROR_MESSAGE}
|
message={FETCH_ERROR_MESSAGE}
|
||||||
openModal={fetchError}
|
openModal={
|
||||||
|
isErrorHealth ||
|
||||||
|
(healthData &&
|
||||||
|
Object.values(healthData).some((value) => value !== "ok"))
|
||||||
|
}
|
||||||
setRetry={() => {
|
setRetry={() => {
|
||||||
checkApplicationHealth();
|
console.log("retrying");
|
||||||
|
refetch();
|
||||||
}}
|
}}
|
||||||
isLoadingHealth={isLoadingHealth}
|
isLoadingHealth={fetchingHealth}
|
||||||
></FetchErrorComponent>
|
></FetchErrorComponent>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,22 +319,6 @@ export async function getVersion() {
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the health status of the API.
|
|
||||||
*
|
|
||||||
* @returns {Promise<AxiosResponse<any>>} A promise that resolves to an AxiosResponse containing the health status.
|
|
||||||
*/
|
|
||||||
export async function getHealth() {
|
|
||||||
return await api.get("/health").catch((e) => {
|
|
||||||
if (e.code === "ECONNABORTED") {
|
|
||||||
console.log("request cancelled");
|
|
||||||
} else {
|
|
||||||
// raise error to be caught by the caller
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}); // Health is the only endpoint that doesn't require /api/v1
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the build status of a flow.
|
* Fetches the build status of a flow.
|
||||||
* @param {string} flowId - The ID of the flow to fetch the build status for.
|
* @param {string} flowId - The ID of the flow to fetch the build status for.
|
||||||
|
|
|
||||||
1
src/frontend/src/controllers/API/queries/health/index.ts
Normal file
1
src/frontend/src/controllers/API/queries/health/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./use-get-health";
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { keepPreviousData } from "@tanstack/react-query";
|
||||||
|
import { useQueryFunctionType } from "../../../../types/api";
|
||||||
|
import { api } from "../../api";
|
||||||
|
import { UseRequestProcessor } from "../../services/request-processor";
|
||||||
|
|
||||||
|
interface getHealthResponse {
|
||||||
|
status: string;
|
||||||
|
chat: string;
|
||||||
|
db: string;
|
||||||
|
folder: string;
|
||||||
|
variables: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useGetHealthQuery: useQueryFunctionType<
|
||||||
|
undefined,
|
||||||
|
getHealthResponse
|
||||||
|
> = (_, onFetch) => {
|
||||||
|
const { query } = UseRequestProcessor();
|
||||||
|
|
||||||
|
const responseFn = (data: getHealthResponse) => {
|
||||||
|
if (!onFetch) return data;
|
||||||
|
if (typeof onFetch === "function") return onFetch(data);
|
||||||
|
switch (onFetch) {
|
||||||
|
default:
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the health status of the API.
|
||||||
|
*
|
||||||
|
* @returns {Promise<AxiosResponse<TransactionsResponse>>} A promise that resolves to an AxiosResponse containing the health status.
|
||||||
|
*/
|
||||||
|
async function getHealthFn() {
|
||||||
|
return await api.get("/health_check");
|
||||||
|
// Health is the only endpoint that doesn't require /api/v1
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryResult = query(
|
||||||
|
["useGetHealthQuery"],
|
||||||
|
async () => {
|
||||||
|
const result = await getHealthFn();
|
||||||
|
return responseFn(result.data);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
|
refetchInterval: 20000,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return queryResult;
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue