feat: pre-check DWH reachability before creating a session (local dev only)
New session now refuses to spawn a Pi runtime that would only die in bootstrap
retrieval when the DWH/vector host is unreachable (e.g. a dropped VPN). Before
`session new`, POST /sessions probes the DWH via `tht db ping`; if it is down it
returns 503 {code:"dwh_unreachable"} with a clear message and creates nothing.
- Gated behind the THT_DWH_PRECHECK flag (default off), enabled only by the local
dev launcher (run-stack.sh) — containers/CI never pay the probe, and existing
tests that don't set it are unaffected.
- ThtRunner.dbPing() runs `tht db ping` with a 10s timeout (run() gains an optional
timeout that SIGKILLs a hung child).
- Frontend: apiFetch throws a typed ApiError (status + parsed payload); the new-
session composer shows the specific alert on `dwh_unreachable` instead of the
generic retry hint, keeping the question for retry.
Verified live on an isolated backend (precheck on + broken DWH host → 503
dwh_unreachable, no session created) and via unit tests (backend 228, frontend 308).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,32 @@ test("a failed create restores the landing view and preserves the question for r
|
||||
expect(FakeEventSource.instances).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("a DWH-unreachable precheck shows a specific alert and preserves the question", async () => {
|
||||
server.use(
|
||||
http.post("http://localhost:8787/sessions", () =>
|
||||
HttpResponse.json(
|
||||
{
|
||||
error: "Cannot start a session: the data warehouse is unreachable. Check the VPN connection and try again.",
|
||||
code: "dwh_unreachable",
|
||||
},
|
||||
{ status: 503 },
|
||||
)),
|
||||
);
|
||||
renderShell();
|
||||
|
||||
const composer = screen.getByRole("textbox", { name: /new question/i });
|
||||
await userEvent.type(composer, "quanti pazienti?");
|
||||
await userEvent.click(screen.getByRole("button", { name: /send/i }));
|
||||
|
||||
// Specific alert, not the generic "failed to create session" hint.
|
||||
expect(await screen.findByText(/data warehouse is unreachable/i)).toBeInTheDocument();
|
||||
expect(screen.queryByText(/failed to create session/i)).not.toBeInTheDocument();
|
||||
// No session was created: landing view stays and the question is kept for retry.
|
||||
expect(screen.getByText(/type your question/i)).toBeInTheDocument();
|
||||
expect(composer).toHaveValue("quanti pazienti?");
|
||||
expect(FakeEventSource.instances).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("model selector shows the three Pi-enabled models and persists the selected provider", async () => {
|
||||
let saved: unknown;
|
||||
server.use(
|
||||
|
||||
Reference in New Issue
Block a user