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:
anovazzi1 2024-07-05 09:03:52 -03:00 committed by GitHub
commit 6160f70011
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 69 additions and 69 deletions

View file

@ -1,4 +1,3 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useContext, useEffect, useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { useNavigate } from "react-router-dom";
@ -13,7 +12,8 @@ import {
FETCH_ERROR_MESSAGE,
} from "./constants/constants";
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 { setupAxiosDefaults } from "./controllers/API/utils";
import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path";
@ -25,21 +25,22 @@ import useFlowsManagerStore from "./stores/flowsManagerStore";
import { useFolderStore } from "./stores/foldersStore";
export default function App() {
const queryClient = new QueryClient();
useTrackLastVisitedPath();
const [fetchError, setFetchError] = useState(false);
const isLoading = useFlowsManagerStore((state) => state.isLoading);
const { isAuthenticated, login, setUserData, setAutoLogin, getUser } =
useContext(AuthContext);
const setLoading = useAlertStore((state) => state.setLoading);
const refreshStars = useDarkStore((state) => state.refreshStars);
const navigate = useNavigate();
const dark = useDarkStore((state) => state.dark);
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
const [isLoadingHealth, setIsLoadingHealth] = useState(false);
const {
data: healthData,
isFetching: fetchingHealth,
isError: isErrorHealth,
refetch,
} = useGetHealthQuery();
useEffect(() => {
if (!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;
return (
@ -161,11 +119,16 @@ export default function App() {
<FetchErrorComponent
description={FETCH_ERROR_DESCRIPION}
message={FETCH_ERROR_MESSAGE}
openModal={fetchError}
openModal={
isErrorHealth ||
(healthData &&
Object.values(healthData).some((value) => value !== "ok"))
}
setRetry={() => {
checkApplicationHealth();
console.log("retrying");
refetch();
}}
isLoadingHealth={isLoadingHealth}
isLoadingHealth={fetchingHealth}
></FetchErrorComponent>
}

View file

@ -319,22 +319,6 @@ export async function getVersion() {
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.
* @param {string} flowId - The ID of the flow to fetch the build status for.

View file

@ -0,0 +1 @@
export * from "./use-get-health";

View file

@ -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;
};