Skip to content

Commit 71ab762

Browse files
committed
Add MB instance health-check banner
1 parent 0d85f6b commit 71ab762

File tree

5 files changed

+118
-0
lines changed

5 files changed

+118
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { Stack, Text } from "@mantine/core"
2+
import { useEffect, useRef, useState } from "react"
3+
import { useQuery } from "@tanstack/react-query"
4+
import { useLocation } from "wouter"
5+
import { METABASE_INSTANCE_HEALTHCHECK_INTERVAL_MS } from "../../constants/metabase-instance-healthcheck-interval"
6+
import { queryMetabaseInstanceStatus } from "../../utils/query-metabase-instance-status"
7+
import { MetabaseHealthStatus } from "../../types/metabase-health-status"
8+
9+
type BannerInfo = {
10+
message: string
11+
}
12+
13+
export const HealthcheckBanner = () => {
14+
const [location, navigate] = useLocation()
15+
const [banner, setBanner] = useState<BannerInfo | null>(null)
16+
17+
const previousStatusRef = useRef<MetabaseHealthStatus | null>(null)
18+
19+
const shouldPoll = previousStatusRef.current === "maintenance"
20+
21+
const { data, isLoading, refetch } = useQuery({
22+
queryKey: ["health"],
23+
queryFn: queryMetabaseInstanceStatus,
24+
refetchInterval: shouldPoll
25+
? METABASE_INSTANCE_HEALTHCHECK_INTERVAL_MS
26+
: false,
27+
})
28+
29+
useEffect(() => {
30+
refetch()
31+
}, [location, refetch])
32+
33+
useEffect(() => {
34+
const currentStatus = data?.status
35+
const previousStatus = previousStatusRef.current
36+
37+
if (!currentStatus || isLoading) {
38+
return
39+
}
40+
41+
const isRecovered =
42+
previousStatus !== null &&
43+
previousStatus !== "ok" &&
44+
currentStatus === "ok"
45+
46+
previousStatusRef.current = currentStatus
47+
48+
if (isRecovered) {
49+
setBanner(null)
50+
navigate(location, { replace: true })
51+
52+
return
53+
}
54+
55+
switch (currentStatus) {
56+
case "ok":
57+
setBanner(null)
58+
break
59+
case "maintenance":
60+
setBanner({
61+
message:
62+
"The embedding demo is undergoing maintenance. Things may not work as expected for a few minutes.",
63+
})
64+
break
65+
default:
66+
setBanner({
67+
message:
68+
"Sorry, the embedding demo is down right now. We're looking into it.",
69+
})
70+
break
71+
}
72+
}, [data, isLoading])
73+
74+
if (!banner) {
75+
return null
76+
}
77+
78+
return (
79+
<Stack
80+
pos="absolute"
81+
top="0"
82+
left="0"
83+
w="100%"
84+
h="100%"
85+
bg="#e5e5e5"
86+
style={{ zIndex: 10000 }}
87+
align="center"
88+
justify="center"
89+
>
90+
<Text c="dark" size="md">
91+
{banner.message}
92+
</Text>
93+
</Stack>
94+
)
95+
}

src/components/layout/Shell.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { FullPageLoader } from "../Loader"
2525
import { SiteFooter } from "../SiteFooter"
2626
import { ProficiencyGradient } from "../ProficiencyGradient"
2727
import { ClickActionDemoModal } from "../ClickActionDemoModal"
28+
import { HealthcheckBanner } from "./HealthcheckBanner"
2829

2930
interface Props {
3031
children: ReactNode
@@ -59,6 +60,8 @@ export function Shell(props: Props) {
5960
}}
6061
>
6162
<AppShell.Header zIndex={102} bg="#2B2F32" className="border-none">
63+
<HealthcheckBanner />
64+
6265
<Flex
6366
justify="space-between"
6467
align="center"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const METABASE_INSTANCE_HEALTHCHECK_INTERVAL_MS = 15000
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type MetabaseHealthStatus = "ok" | "maintenance" | "error" | string
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { METABASE_INSTANCE_URL } from "../constants/env"
2+
import { MetabaseHealthStatus } from "../types/metabase-health-status"
3+
4+
export async function queryMetabaseInstanceStatus(): Promise<{
5+
status: MetabaseHealthStatus
6+
}> {
7+
try {
8+
const response = await fetch(`${METABASE_INSTANCE_URL}/api/health`)
9+
10+
if (!response.ok) {
11+
return { status: "error" }
12+
}
13+
14+
return response.json()
15+
} catch {
16+
return { status: "error" }
17+
}
18+
}

0 commit comments

Comments
 (0)