-
+
+
+
+
+
+ {backHref && (
+
+ )}
+
{title}
+
+
+
+ {reasons.length > 0 && (
+
+
+ {expanded && (
+
+ {reasons.map((reason, i) => (
+ -
+
+ {reason}
+
+ ))}
+
+ )}
+
+ )}
)
}
diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts
index 1d93562..9612788 100644
--- a/web/src/lib/api.ts
+++ b/web/src/lib/api.ts
@@ -384,6 +384,7 @@ export type DbInfo = {
server_max_connections: number | null;
main_pool_size: number;
backfill_pool_size: number;
+ restart_recommended: boolean;
};
export function getDbInfo() {
diff --git a/web/src/lib/restart-context.tsx b/web/src/lib/restart-context.tsx
new file mode 100644
index 0000000..a503e61
--- /dev/null
+++ b/web/src/lib/restart-context.tsx
@@ -0,0 +1,47 @@
+"use client";
+
+import { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
+
+interface RestartContextType {
+ reasons: string[];
+ addReason: (key: string, reason: string) => void;
+ removeReason: (key: string) => void;
+}
+
+const RestartContext = createContext
({
+ reasons: [],
+ addReason: () => {},
+ removeReason: () => {},
+});
+
+export function RestartProvider({ children }: { children: React.ReactNode }) {
+ const [reasonMap, setReasonMap] = useState>({});
+ const reasonMapRef = useRef(reasonMap);
+ reasonMapRef.current = reasonMap;
+
+ const addReason = useCallback((key: string, reason: string) => {
+ if (reasonMapRef.current[key] === reason) return;
+ setReasonMap((prev) => ({ ...prev, [key]: reason }));
+ }, []);
+
+ const removeReason = useCallback((key: string) => {
+ setReasonMap((prev) => {
+ if (!(key in prev)) return prev;
+ const next = { ...prev };
+ delete next[key];
+ return next;
+ });
+ }, []);
+
+ const reasons = useMemo(() => Object.values(reasonMap), [reasonMap]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useRestart() {
+ return useContext(RestartContext);
+}