|
|
|
@ -1,17 +1,23 @@
|
|
|
|
|
import { FC, PropsWithChildren, useEffect, useState } from "react"; |
|
|
|
|
import { IconAlertTriangle } from "@tabler/icons-react"; |
|
|
|
|
import { useAppDispatch } from "../state/hooks"; |
|
|
|
|
import { updateSettings, useSettings } from "../state/settingsSlice"; |
|
|
|
|
import { useSuspenseAPIQuery } from "../api/api"; |
|
|
|
|
import { WALReplayStatus } from "../api/responseTypes/walreplay"; |
|
|
|
|
import { Progress, Stack, Title } from "@mantine/core"; |
|
|
|
|
import { Progress, Alert } from "@mantine/core"; |
|
|
|
|
import { useSuspenseQuery } from "@tanstack/react-query"; |
|
|
|
|
|
|
|
|
|
const STATUS_STARTING = "is starting up..."; |
|
|
|
|
const STATUS_STOPPING = "is shutting down..."; |
|
|
|
|
const STATUS_LOADING = "is not ready..."; |
|
|
|
|
|
|
|
|
|
const ReadinessLoader: FC = () => { |
|
|
|
|
const { pathPrefix } = useSettings(); |
|
|
|
|
const { pathPrefix, agentMode } = useSettings(); |
|
|
|
|
const dispatch = useAppDispatch(); |
|
|
|
|
|
|
|
|
|
// Query key is incremented every second to retrigger the status fetching.
|
|
|
|
|
const [queryKey, setQueryKey] = useState(0); |
|
|
|
|
const [statusMessage, setStatusMessage] = useState(""); |
|
|
|
|
|
|
|
|
|
// Query readiness status.
|
|
|
|
|
const { data: ready } = useSuspenseQuery<boolean>({ |
|
|
|
@ -28,8 +34,16 @@ const ReadinessLoader: FC = () => {
|
|
|
|
|
}); |
|
|
|
|
switch (res.status) { |
|
|
|
|
case 200: |
|
|
|
|
setStatusMessage(""); // Clear any status message when ready.
|
|
|
|
|
return true; |
|
|
|
|
case 503: |
|
|
|
|
// Check the custom header `X-Prometheus-Stopping` for stopping information.
|
|
|
|
|
if (res.headers.get("X-Prometheus-Stopping") === "true") { |
|
|
|
|
setStatusMessage(STATUS_STOPPING); |
|
|
|
|
} else { |
|
|
|
|
setStatusMessage(STATUS_STARTING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
default: |
|
|
|
|
throw new Error(res.statusText); |
|
|
|
@ -40,14 +54,16 @@ const ReadinessLoader: FC = () => {
|
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Query WAL replay status.
|
|
|
|
|
// Only call WAL replay status API if the service is starting up.
|
|
|
|
|
const shouldQueryWALReplay = statusMessage === STATUS_STARTING; |
|
|
|
|
|
|
|
|
|
const { |
|
|
|
|
data: { |
|
|
|
|
data: { min, max, current }, |
|
|
|
|
}, |
|
|
|
|
data: walData, |
|
|
|
|
isSuccess: walSuccess, |
|
|
|
|
} = useSuspenseAPIQuery<WALReplayStatus>({ |
|
|
|
|
path: "/status/walreplay", |
|
|
|
|
key: ["walreplay", queryKey], |
|
|
|
|
enabled: shouldQueryWALReplay, // Only enabled when service is starting up.
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
@ -62,21 +78,28 @@ const ReadinessLoader: FC = () => {
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<Stack gap="lg" maw={1000} mx="auto" mt="xs"> |
|
|
|
|
<Title order={2}>Starting up...</Title> |
|
|
|
|
{max > 0 && ( |
|
|
|
|
<Alert |
|
|
|
|
color="yellow" |
|
|
|
|
title={"Prometheus " + (agentMode && "Agent "||"") + (statusMessage || STATUS_LOADING)} |
|
|
|
|
icon={<IconAlertTriangle/>} |
|
|
|
|
maw={500} |
|
|
|
|
mx="auto" |
|
|
|
|
mt="lg" |
|
|
|
|
> |
|
|
|
|
{shouldQueryWALReplay && walSuccess && walData && ( |
|
|
|
|
<> |
|
|
|
|
<p> |
|
|
|
|
Replaying WAL ({current}/{max}) |
|
|
|
|
</p> |
|
|
|
|
<strong> |
|
|
|
|
Replaying WAL ({walData.data.current}/{walData.data.max}) |
|
|
|
|
</strong> |
|
|
|
|
<Progress |
|
|
|
|
size="xl" |
|
|
|
|
animated |
|
|
|
|
value={((current - min + 1) / (max - min + 1)) * 100} |
|
|
|
|
color="yellow" |
|
|
|
|
value={((walData.data.current - walData.data.min + 1) / (walData.data.max - walData.data.min + 1)) * 100} |
|
|
|
|
/> |
|
|
|
|
</> |
|
|
|
|
)} |
|
|
|
|
</Stack> |
|
|
|
|
</Alert> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|