"use client"; /** * T-177 — Search health tab: index vs source-of-truth document counts (drift), * indexing lag, the last reconcile stamp, and the T-156 full-reindex trigger. * * `sourceCount` is the Postgres `searchDocument` mirror (what the worker's * reconcile compares against); `docCount` is the OpenSearch whole-doc count * (chunks excluded, org-scoped). Drift = docCount − sourceCount. When * OpenSearch is down the API returns `healthy:false` (200, never 500) with a * stable `error` code — this tab surfaces that instead of a spinner loop. */ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Loader2, RefreshCw } from "lucide-react"; import { orgAdminApi } from "@/lib/org-admin"; import { isApiError } from "@/lib/api"; import { toast } from "@/stores/ui-store"; import { Section } from "@/components/settings/settings-shell"; function fmtDuration(ms: number | null): string { if (ms === null) return "—"; if (ms < 1000) return `${ms} ms`; const s = Math.floor(ms / 1000); if (s < 60) return `${s} s`; const m = Math.floor(s / 60); if (m < 60) return `${m} m ${s % 60} s`; const h = Math.floor(m / 60); if (h < 24) return `${h} h ${m % 60} m`; return `${Math.floor(h / 24)} d ${h % 24} h`; } function fmtTime(iso: string | null): string { if (!iso) return "unknown"; return new Date(iso).toLocaleString(); } export function AdminSearchHealthTab({ orgId }: { orgId: string }) { const qc = useQueryClient(); const health = useQuery({ queryKey: ["orgs", orgId, "admin", "search", "health"], queryFn: () => orgAdminApi.searchHealth(orgId), retry: false, refetchInterval: 15_000, }); const reindex = useMutation({ mutationFn: () => orgAdminApi.searchReindex(orgId), onSuccess: (res) => { toast("success", "Reindex enqueued — the worker will rebuild the index"); void res; qc.invalidateQueries({ queryKey: ["orgs", orgId, "admin", "search", "health"] }); }, onError: (e) => toast("error", "Could not enqueue the reindex", isApiError(e) ? e.message : undefined) }); if (health.isLoading) { return
Loading search health…
; } if (health.isError) { returnCould not load the search health.
; } const h = health.data!; return (OpenSearch did not answer ({h.error ?? "unknown error"}). The counts below are from the Postgres source of truth only.