fix(backend): check read-only 409 before the Ollama preflight on resume
This commit is contained in:
@@ -50,12 +50,12 @@ export function sessionRoutes(
|
|||||||
});
|
});
|
||||||
app.post("/sessions/:id/resume", async (req, reply) => {
|
app.post("/sessions/:id/resume", async (req, reply) => {
|
||||||
const id = (req.params as any).id;
|
const id = (req.params as any).id;
|
||||||
const ensure = await d.tht.ollamaEnsure(d.getSettings().workspace ?? "", d.ollamaEnsureTimeoutSec);
|
|
||||||
if (!ensure.ok) return reply.code(503).send({ error: ensure.error ?? "Ollama/embeddings non disponibili" });
|
|
||||||
const manifest = (await d.tht.sessionShow(id)) as { status?: string; archived?: boolean } | null;
|
const manifest = (await d.tht.sessionShow(id)) as { status?: string; archived?: boolean } | null;
|
||||||
if (manifest?.status === "finalized" || manifest?.archived) {
|
if (manifest?.status === "finalized" || manifest?.archived) {
|
||||||
return reply.code(409).send({ error: "sessione in sola lettura (finalizzata o archiviata)" });
|
return reply.code(409).send({ error: "sessione in sola lettura (finalizzata o archiviata)" });
|
||||||
}
|
}
|
||||||
|
const ensure = await d.tht.ollamaEnsure(d.getSettings().workspace ?? "", d.ollamaEnsureTimeoutSec);
|
||||||
|
if (!ensure.ok) return reply.code(503).send({ error: ensure.error ?? "Ollama/embeddings non disponibili" });
|
||||||
const rt = await d.mgr.resume(id, d.tht);
|
const rt = await d.mgr.resume(id, d.tht);
|
||||||
rt.bridge.onClientEvent((e) => d.hub.publish(id, e.type, e));
|
rt.bridge.onClientEvent((e) => d.hub.publish(id, e.type, e));
|
||||||
return reply.code(200).send({ id });
|
return reply.code(200).send({ id });
|
||||||
|
|||||||
@@ -152,6 +152,17 @@ test("POST /sessions proceeds when ollamaEnsure succeeds", async () => {
|
|||||||
expect(ensureWs).toBe("psd");
|
expect(ensureWs).toBe("psd");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("POST /sessions/:id/resume returns 409 for a read-only session without calling ollamaEnsure", async () => {
|
||||||
|
let ensureCalled = false;
|
||||||
|
const app = mutApp({
|
||||||
|
sessionShow: async () => ({ status: "finalized", archived: false }),
|
||||||
|
ollamaEnsure: async () => { ensureCalled = true; return { ok: false, error: "down" }; },
|
||||||
|
});
|
||||||
|
const res = await app.inject({ method: "POST", url: "/sessions/s1/resume" });
|
||||||
|
expect(res.statusCode).toBe(409);
|
||||||
|
expect(ensureCalled).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
test("POST /sessions/:id/resume refuses with 503 when ollamaEnsure fails", async () => {
|
test("POST /sessions/:id/resume refuses with 503 when ollamaEnsure fails", async () => {
|
||||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||||
thtRunner: {
|
thtRunner: {
|
||||||
|
|||||||
@@ -103,9 +103,10 @@ and the start spawn behind a seam.
|
|||||||
The preflight runs **first**, before any session is created or resumed:
|
The preflight runs **first**, before any session is created or resumed:
|
||||||
- `POST /sessions`: `const r = await tht.ollamaEnsure(settings.workspace, timeout)`. If `!r.ok`
|
- `POST /sessions`: `const r = await tht.ollamaEnsure(settings.workspace, timeout)`. If `!r.ok`
|
||||||
→ `reply.code(503).send({ error: r.error })` and **return** (do NOT call `sessionNew`/`spawnFor`).
|
→ `reply.code(503).send({ error: r.error })` and **return** (do NOT call `sessionNew`/`spawnFor`).
|
||||||
- `POST /sessions/:id/resume`: same preflight **before** the existing finalized/archived guard
|
- `POST /sessions/:id/resume`: the finalized/archived guard runs **first** — a read-only session
|
||||||
and `mgr.resume`. On failure → 503, no spawn. (Uses the session's workspace — the current
|
is rejected with 409 without touching Ollama. The preflight runs **after** that guard and
|
||||||
configured/settings workspace, consistent with how resume resolves the session.)
|
**before** `mgr.resume`. On failure → 503, no spawn. (Uses the session's workspace — the
|
||||||
|
current configured/settings workspace, consistent with how resume resolves the session.)
|
||||||
|
|
||||||
### Config ([config.ts](../../../backend/src/config.ts))
|
### Config ([config.ts](../../../backend/src/config.ts))
|
||||||
- `ollamaEnsureTimeoutMs: number` from `OLLAMA_ENSURE_TIMEOUT_MS` (default `60000`); passed to
|
- `ollamaEnsureTimeoutMs: number` from `OLLAMA_ENSURE_TIMEOUT_MS` (default `60000`); passed to
|
||||||
|
|||||||
Reference in New Issue
Block a user