File size: 2,063 Bytes
e94832e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | /** Is the page talking to the server it was built with?
*
* A stale uvicorn cost an hour once: the console showed the new UI, every
* request went to a process started before the endpoints existed, and the
* symptom was a plain "Not Found" that looked like a frontend bug. The commit
* is stamped into both halves at build and start, so the answer is now one
* comparison rather than an investigation.
*/
import { useEffect, useState } from "react";
import { API_BASE } from "../api/client";
export interface BuildState {
ours: string;
theirs: string | null;
startedAt: string | null;
routes: number | null;
/** Both sides known, and different. */
mismatch: boolean;
/** The API did not answer /version at all — an old build, or nothing running. */
unreachable: boolean;
}
export function useBuildCheck(): BuildState {
const ours = typeof __APP_COMMIT__ === "string" ? __APP_COMMIT__ : "unknown";
const [state, setState] = useState<BuildState>({
ours,
theirs: null,
startedAt: null,
routes: null,
mismatch: false,
unreachable: false,
});
useEffect(() => {
const controller = new AbortController();
fetch(`${API_BASE}/version`, { signal: controller.signal })
.then((response) => (response.ok ? response.json() : Promise.reject(response.statusText)))
.then((body: { commit: string; started_at: string; routes: number }) =>
setState({
ours,
theirs: body.commit,
startedAt: body.started_at,
routes: body.routes,
// "unknown" on either side means someone built without git; that is
// not evidence of staleness, so it is not reported as such.
mismatch:
body.commit !== ours && body.commit !== "unknown" && ours !== "unknown",
unreachable: false,
}),
)
.catch(() => {
if (controller.signal.aborted) return;
setState((current) => ({ ...current, unreachable: true }));
});
return () => controller.abort();
}, [ours]);
return state;
}
|