feat(mcp): resume queued calculation jobs
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { expect, it, mock } from "bun:test";
|
||||
import { createTaskCalculationWaiter } from "../../src/mcp/task-calculation-waiter.js";
|
||||
const owner = { context: { sessionId: "s", clientSessionId: "c", actorKey: "a", projectKey: "p", projectId: "p", traceId: "t", purpose: "task_execution" as const }, runtimeSessionId: "s" };
|
||||
const result = (status: string) => ({ content: [], structuredContent: { data: [{ job_id: "job-1", status, poll_after_ms: 1500 }], page: { has_more: false } } });
|
||||
it("waits in the host across bounded status reads then resumes once for terminal results", async () => {
|
||||
const outputs = [result("queued"), result("running"), result("succeeded"), result("succeeded")];
|
||||
const query = mock(async () => outputs.shift()!);
|
||||
const pause = mock(async (_ms: number, _signal: AbortSignal) => {});
|
||||
const wait = createTaskCalculationWaiter({ query }, () => owner, pause);
|
||||
const signal = new AbortController().signal;
|
||||
expect(await wait("s", signal)).toContain("get_calculation_result");
|
||||
expect(pause).toHaveBeenCalledTimes(2);
|
||||
expect(pause.mock.calls[0]?.[0]).toBe(1500);
|
||||
expect(await wait("s", signal)).toBeNull();
|
||||
expect(query).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
it("does not turn unavailable status into a completed task", async () => {
|
||||
const query = mock(async () => ({ content: [], isError: true }));
|
||||
await expect(createTaskCalculationWaiter({ query }, () => owner)("s", new AbortController().signal)).rejects.toThrow("unavailable");
|
||||
});
|
||||
it("aborts host waiting without issuing Server cancellation", async () => {
|
||||
const controller = new AbortController();
|
||||
const names: string[] = [];
|
||||
const query = mock(async (_id: string, _owner: unknown, name: string) => { names.push(name); return result("running"); });
|
||||
const wait = createTaskCalculationWaiter({ query }, () => owner, async () => { controller.abort(); });
|
||||
await expect(wait("s", controller.signal)).rejects.toThrow();
|
||||
expect(names).toEqual(["list_calculation_jobs"]);
|
||||
});
|
||||
|
||||
it("resumes recovery for a worker-interrupted job instead of waiting or completing silently", async () => {
|
||||
const query = mock(async () => result("interrupted"));
|
||||
const pause = mock(async (_ms: number, _signal: AbortSignal) => {});
|
||||
const wait = createTaskCalculationWaiter({ query }, () => owner, pause);
|
||||
const resume = await wait("s", new AbortController().signal);
|
||||
expect(resume).toContain("interrupted");
|
||||
expect(resume).toContain("不要重复提交");
|
||||
expect(pause).not.toHaveBeenCalled();
|
||||
});
|
||||
Reference in New Issue
Block a user