vega-frontend-monorepo/libs/environment/src/hooks/use-node-health.ts
2023-11-30 07:31:44 +00:00

94 lines
2.8 KiB
TypeScript

import { useEffect, useMemo } from 'react';
import { useNodeCheckQuery } from '../utils/__generated__/NodeCheck';
import { useHeaderStore } from '@vegaprotocol/apollo-client';
import { useEnvironment } from './use-environment';
import { useNavigatorOnline } from '@vegaprotocol/react-helpers';
import { Intent } from '@vegaprotocol/ui-toolkit';
import { isTestEnv } from '@vegaprotocol/utils';
import { useT } from '../use-t';
const POLL_INTERVAL = 1000;
const BLOCK_THRESHOLD = 3;
const ERROR_LATENCY = 10000;
const WARNING_LATENCY = 3000;
export const useNodeHealth = () => {
const t = useT();
const online = useNavigatorOnline();
const url = useEnvironment((store) => store.VEGA_URL);
const headerStore = useHeaderStore();
const headers = url ? headerStore[url] : undefined;
const { data, error, startPolling, stopPolling } = useNodeCheckQuery({
fetchPolicy: 'no-cache',
});
const blockDiff = useMemo(() => {
if (!data?.statistics?.blockHeight) {
return null;
}
if (!headers?.blockHeight) {
return 0;
}
return Number(data.statistics.blockHeight) - headers.blockHeight;
}, [data?.statistics?.blockHeight, headers?.blockHeight]);
useEffect(() => {
if (error) {
stopPolling();
return;
}
if (!isTestEnv() && window.location.hostname !== 'localhost') {
startPolling(POLL_INTERVAL);
}
}, [error, startPolling, stopPolling]);
const blockUpdateMsLatency = headers?.timestamp
? Date.now() - headers.timestamp.getTime()
: 0;
const [text, intent] = useMemo(() => {
let intent = Intent.Success;
let text = t('Operational');
if (!online) {
text = t('Offline');
intent = Intent.Danger;
} else if (blockDiff === null) {
// Block height query failed and null was returned
text = t('Non operational');
intent = Intent.Danger;
} else if (blockUpdateMsLatency > ERROR_LATENCY) {
text = t(
'Erroneous latency ( >{{errorLatency}} sec): {{blockUpdateLatency}} sec',
{
errorLatency: (ERROR_LATENCY / 1000).toString(),
blockUpdateLatency: (blockUpdateMsLatency / 1000).toFixed(2),
}
);
intent = Intent.Danger;
} else if (blockDiff >= BLOCK_THRESHOLD) {
text = t('blocksBehind', '{{count}} Blocks behind', { count: blockDiff });
intent = Intent.Warning;
} else if (blockUpdateMsLatency > WARNING_LATENCY) {
text = t(
'Warning delay ( >{{warningLatency}} sec): {{blockUpdateLatency}} sec',
{
warningLatency: (WARNING_LATENCY / 1000).toString(),
blockUpdateLatency: (blockUpdateMsLatency / 1000).toFixed(2),
}
);
intent = Intent.Warning;
}
return [text, intent];
}, [online, blockDiff, blockUpdateMsLatency, t]);
return {
datanodeBlockHeight: headers?.blockHeight,
text,
intent,
};
};