Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 6x 6x 7x 1x 7x 14x 7x 7x 3x 3x 1x 13x | "use client";
// The shared session status-PATCH client helper (spec §3.2; plan Task 16).
// Every session-state transition that can strand queued decisions routes its
// fetch through here so the flush rule lives in ONE place:
//
// - paused → best-effort, NON-BLOCKING pre-flush (F8): wait at most
// PAUSE_PREFLUSH_BOUND_MS, then PATCH regardless — stepping away
// is never gated on the network (the queue persists and
// PendingDecisionsGate recovers it on return).
// - terminal → strict flush-then-complete (spec §3.2 / parent ARCH-2): the
// drain is fully awaited and a taxonomy-stopped drain (entries
// left behind) FAILS the transition — a terminal session would
// 409 those entries and recovery would discard them.
// (No production caller PATCHes a terminal status today; Epic 5's
// Decide surface becomes the first — it inherits the rule.)
// - active → plain PATCH, no flush (resuming changes nothing to land).
import { drain, triggerFlush } from "./decisionFlusher";
import { readQueue, type QueueKey } from "./decisionQueue";
export const PAUSE_PREFLUSH_BOUND_MS = 2_000;
export type SessionStatus = "active" | "paused" | "completed" | "abandoned";
async function preflushBounded(key: QueueKey): Promise<void> {
await Promise.race([
triggerFlush(key).catch(() => undefined), // a stumbling flush never blocks the person
new Promise<void>((resolve) => {
setTimeout(resolve, PAUSE_PREFLUSH_BOUND_MS);
}),
]);
}
export async function patchSessionStatus(key: QueueKey, status: SessionStatus): Promise<Response> {
if (status === "paused") {
await preflushBounded(key);
} else if (status === "completed" || status === "abandoned") {
await drain([key]);
if (readQueue(key).length > 0) {
// The drain stopped per the taxonomy (401/403/409/…) with entries still
// queued — completing now would strand them behind a terminal session.
throw new Error("Some answers are still on their way — this can finish once they land.");
}
}
return fetch(`/api/sessions/${key.sessionId}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ status }),
});
}
|