diff --git a/apps/docs/src/components/status-indicator.tsx b/apps/docs/src/components/status-indicator.tsx index 0f6655ba7c..d48bf31066 100644 --- a/apps/docs/src/components/status-indicator.tsx +++ b/apps/docs/src/components/status-indicator.tsx @@ -12,6 +12,14 @@ interface StatusResponse { }; } +interface Incident { + impact: StatusIndicator; +} + +interface IncidentsResponse { + incidents: Incident[]; +} + const dotColors: Record = { none: "bg-green-500", minor: "bg-yellow-500", @@ -19,6 +27,13 @@ const dotColors: Record = { critical: "bg-red-500", }; +const SEVERITY: Record = { + none: 0, + minor: 1, + major: 2, + critical: 3, +}; + const POLL_INTERVAL = 5 * 60 * 1000; // 5 minutes export function StatusIndicator() { @@ -26,10 +41,39 @@ export function StatusIndicator() { useEffect(() => { const fetchStatus = () => { - fetch("https://www.prisma-status.com/api/v2/status.json") - .then((res) => res.json()) - .then((data: StatusResponse) => setStatus(data.status)) - .catch(() => setStatus(null)); + Promise.allSettled([ + fetch("https://www.prisma-status.com/api/v2/status.json").then( + (res) => res.json() as Promise, + ), + fetch("https://www.prisma-status.com/api/v2/incidents/unresolved.json").then( + (res) => res.json() as Promise, + ), + ]).then(([statusResult, incidentsResult]) => { + if (statusResult.status === "rejected") { + setStatus(null); + return; + } + + const statusData = statusResult.value; + const incidents = + incidentsResult.status === "fulfilled" + ? (incidentsResult.value.incidents ?? []) + : []; + const worstIncidentIndicator = incidents.reduce( + (worst, incident) => + SEVERITY[incident.impact] > SEVERITY[worst] ? incident.impact : worst, + "none", + ); + + if (SEVERITY[worstIncidentIndicator] > SEVERITY[statusData.status.indicator]) { + setStatus({ + indicator: worstIncidentIndicator, + description: incidents.length === 1 ? "Active Incident" : "Active Incidents", + }); + } else { + setStatus(statusData.status); + } + }); }; fetchStatus(); diff --git a/packages/ui/src/components/pdp-status.tsx b/packages/ui/src/components/pdp-status.tsx index ba2cff4824..5423341831 100644 --- a/packages/ui/src/components/pdp-status.tsx +++ b/packages/ui/src/components/pdp-status.tsx @@ -2,6 +2,23 @@ import { useEffect, useState } from "react"; import { cn } from "../lib/cn"; +type StatusIndicator = "none" | "minor" | "major" | "critical"; + +interface Incident { + impact: StatusIndicator; +} + +interface IncidentsResponse { + incidents: Incident[]; +} + +const SEVERITY: Record = { + none: 0, + minor: 1, + major: 2, + critical: 3, +}; + const indicatorStatus: Record = { "-": "[&>div]:bg-gray-500 text-foreground-neutral-weak", none: "[&>div]:bg-background-success-reverse-strong text-background-success-reverse-strong", @@ -19,14 +36,35 @@ const PDPStatus = ({ className }: { className?: string }) => { }); useEffect(() => { - fetch("https://www.prisma-status.com/api/v2/status.json") - .then((response) => response.json()) - .then((json) => { - setPdpStatus(json); + Promise.all([ + fetch("https://www.prisma-status.com/api/v2/status.json").then( + (res) => res.json(), + ), + fetch("https://www.prisma-status.com/api/v2/incidents/unresolved.json").then( + (res) => res.json() as Promise, + ), + ]) + .then(([statusJson, incidentsData]) => { + const summaryIndicator: StatusIndicator = statusJson.status.indicator ?? "none"; + const incidents: Incident[] = incidentsData.incidents ?? []; + const worstIncidentIndicator = incidents.reduce( + (worst, incident) => + SEVERITY[incident.impact] > SEVERITY[worst] ? incident.impact : worst, + "none", + ); + + if (SEVERITY[worstIncidentIndicator] > SEVERITY[summaryIndicator]) { + setPdpStatus({ + status: { + indicator: worstIncidentIndicator, + description: incidents.length === 1 ? "Active Incident" : "Active Incidents", + }, + }); + } else { + setPdpStatus(statusJson); + } }) - .catch((error) => - console.log("PDP Status fetch failed " + error.message), - ); + .catch((error) => console.log("PDP Status fetch failed " + error.message)); }, []); const indicator = pdpStatus.status.indicator || "-";