From 1eed0e1e99d5e53fbc5da142a32beb38bfd6cd36 Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 16 Oct 2024 08:03:36 +0100 Subject: [PATCH] im dumb --- projects/backend/Dockerfile | 2 +- projects/common/src/utils/api-utils.ts | 23 ++++++++++ projects/website/src/app/layout.tsx | 2 + .../website/src/components/api/api-health.tsx | 45 +++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 projects/common/src/utils/api-utils.ts create mode 100644 projects/website/src/components/api/api-health.tsx diff --git a/projects/backend/Dockerfile b/projects/backend/Dockerfile index 492a31c..3e71d7f 100644 --- a/projects/backend/Dockerfile +++ b/projects/backend/Dockerfile @@ -25,6 +25,6 @@ RUN bun --filter '@ssr/common' build COPY --from=depends /app/projects/backend ./projects/backend # Lint before starting -RUN bun --filter 'website' lint +RUN bun --filter 'backend' lint CMD ["bun", "run", "--filter", "backend", "start"] diff --git a/projects/common/src/utils/api-utils.ts b/projects/common/src/utils/api-utils.ts new file mode 100644 index 0000000..8dc00cc --- /dev/null +++ b/projects/common/src/utils/api-utils.ts @@ -0,0 +1,23 @@ +import ky from "ky"; + +type ApiHealth = { + online: boolean; +}; + +/** + * Gets the health of the api server. + * + * @param url the url of the api + */ +export async function getApiHealth(url: string): Promise { + try { + await ky.get(url); + return { + online: true, + }; + } catch { + return { + online: false, + }; + } +} diff --git a/projects/website/src/app/layout.tsx b/projects/website/src/app/layout.tsx index e040075..1b0fa25 100644 --- a/projects/website/src/app/layout.tsx +++ b/projects/website/src/app/layout.tsx @@ -14,6 +14,7 @@ import NavBar from "../components/navbar/navbar"; import { Colors } from "@/common/colors"; import OfflineNetwork from "@/components/offline-network"; import Script from "next/script"; +import { ApiHealth } from "@/components/api/api-health"; const siteFont = localFont({ src: "./fonts/JetBrainsMono.ttf", @@ -79,6 +80,7 @@ export default function RootLayout({ +
diff --git a/projects/website/src/components/api/api-health.tsx b/projects/website/src/components/api/api-health.tsx new file mode 100644 index 0000000..d820228 --- /dev/null +++ b/projects/website/src/components/api/api-health.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { useQuery } from "@tanstack/react-query"; +import { useEffect, useRef, useState } from "react"; +import { getApiHealth } from "@ssr/common/utils/api-utils"; +import { config } from "../../../config"; +import { useToast } from "@/hooks/use-toast"; +import { useIsFirstRender } from "@uidotdev/usehooks"; + +export function ApiHealth() { + const { toast } = useToast(); + const firstRender = useIsFirstRender(); + const [online, setOnline] = useState(true); + const previousOnlineStatus = useRef(true); + + useQuery({ + queryKey: ["api-health"], + queryFn: async () => { + const status = (await getApiHealth(config.siteApi)).online; + setOnline(status); + return status; + }, + refetchInterval: 1000 * 15, + }); + + useEffect(() => { + if (firstRender) { + return; + } + + // Trigger toast only if the online status changes + if (previousOnlineStatus.current !== online) { + toast({ + title: `The API is now ${online ? "Online" : "Offline"}!`, + description: online ? "The API has recovered connectivity." : "The API has lost connectivity.", + variant: online ? "success" : "destructive", + }); + } + + // Update the previous online status + previousOnlineStatus.current = online; + }, [firstRender, online, toast]); + + return <>; +}