@mcpmesh/sdk 1.3.4 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/a2a/a2a-bearer.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-bearer.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-bearer.spec.js +58 -0
- package/dist/__tests__/a2a/a2a-bearer.spec.js.map +1 -0
- package/dist/__tests__/a2a/a2a-client.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-client.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-client.spec.js +334 -0
- package/dist/__tests__/a2a/a2a-client.spec.js.map +1 -0
- package/dist/__tests__/a2a/a2a-job.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-job.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-job.spec.js +255 -0
- package/dist/__tests__/a2a/a2a-job.spec.js.map +1 -0
- package/dist/__tests__/a2a/a2a-stream.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-stream.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-stream.spec.js +278 -0
- package/dist/__tests__/a2a/a2a-stream.spec.js.map +1 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.d.ts +2 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.js +262 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.js +127 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.js +113 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.js +850 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.js +164 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/mount.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/mount.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/mount.spec.js +433 -0
- package/dist/__tests__/a2a/producer/mount.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.js +116 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.js +754 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.js +124 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/task-store.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/task-store.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/task-store.spec.js +180 -0
- package/dist/__tests__/a2a/producer/task-store.spec.js.map +1 -0
- package/dist/__tests__/agent-add-tool.spec.d.ts +2 -0
- package/dist/__tests__/agent-add-tool.spec.d.ts.map +1 -0
- package/dist/__tests__/agent-add-tool.spec.js +483 -0
- package/dist/__tests__/agent-add-tool.spec.js.map +1 -0
- package/dist/__tests__/api-runtime-race.spec.d.ts +2 -0
- package/dist/__tests__/api-runtime-race.spec.d.ts.map +1 -0
- package/dist/__tests__/api-runtime-race.spec.js +193 -0
- package/dist/__tests__/api-runtime-race.spec.js.map +1 -0
- package/dist/__tests__/claim-dispatcher.spec.d.ts +2 -0
- package/dist/__tests__/claim-dispatcher.spec.d.ts.map +1 -0
- package/dist/__tests__/claim-dispatcher.spec.js +408 -0
- package/dist/__tests__/claim-dispatcher.spec.js.map +1 -0
- package/dist/__tests__/inbound-job-dispatch.spec.d.ts +2 -0
- package/dist/__tests__/inbound-job-dispatch.spec.d.ts.map +1 -0
- package/dist/__tests__/inbound-job-dispatch.spec.js +185 -0
- package/dist/__tests__/inbound-job-dispatch.spec.js.map +1 -0
- package/dist/__tests__/job-controller-progress.spec.d.ts +2 -0
- package/dist/__tests__/job-controller-progress.spec.d.ts.map +1 -0
- package/dist/__tests__/job-controller-progress.spec.js +85 -0
- package/dist/__tests__/job-controller-progress.spec.js.map +1 -0
- package/dist/__tests__/jobs-cancel-route.spec.d.ts +2 -0
- package/dist/__tests__/jobs-cancel-route.spec.d.ts.map +1 -0
- package/dist/__tests__/jobs-cancel-route.spec.js +88 -0
- package/dist/__tests__/jobs-cancel-route.spec.js.map +1 -0
- package/dist/__tests__/llm-agent-stream.test.d.ts +14 -0
- package/dist/__tests__/llm-agent-stream.test.d.ts.map +1 -0
- package/dist/__tests__/llm-agent-stream.test.js +341 -0
- package/dist/__tests__/llm-agent-stream.test.js.map +1 -0
- package/dist/__tests__/llm-provider.test.js +22 -1
- package/dist/__tests__/llm-provider.test.js.map +1 -1
- package/dist/__tests__/media-resolver.test.js +40 -0
- package/dist/__tests__/media-resolver.test.js.map +1 -1
- package/dist/__tests__/mesh-job-submitter.spec.d.ts +2 -0
- package/dist/__tests__/mesh-job-submitter.spec.d.ts.map +1 -0
- package/dist/__tests__/mesh-job-submitter.spec.js +110 -0
- package/dist/__tests__/mesh-job-submitter.spec.js.map +1 -0
- package/dist/__tests__/proxy-stream.test.d.ts +9 -0
- package/dist/__tests__/proxy-stream.test.d.ts.map +1 -0
- package/dist/__tests__/proxy-stream.test.js +347 -0
- package/dist/__tests__/proxy-stream.test.js.map +1 -0
- package/dist/__tests__/resolver-meshjob.spec.d.ts +26 -0
- package/dist/__tests__/resolver-meshjob.spec.d.ts.map +1 -0
- package/dist/__tests__/resolver-meshjob.spec.js +201 -0
- package/dist/__tests__/resolver-meshjob.spec.js.map +1 -0
- package/dist/__tests__/schema-verdict-policy.test.d.ts +6 -0
- package/dist/__tests__/schema-verdict-policy.test.d.ts.map +1 -0
- package/dist/__tests__/schema-verdict-policy.test.js +126 -0
- package/dist/__tests__/schema-verdict-policy.test.js.map +1 -0
- package/dist/__tests__/sse-stream.test.d.ts +12 -0
- package/dist/__tests__/sse-stream.test.d.ts.map +1 -0
- package/dist/__tests__/sse-stream.test.js +170 -0
- package/dist/__tests__/sse-stream.test.js.map +1 -0
- package/dist/a2a/a2a-bearer.d.ts +27 -0
- package/dist/a2a/a2a-bearer.d.ts.map +1 -0
- package/dist/a2a/a2a-bearer.js +63 -0
- package/dist/a2a/a2a-bearer.js.map +1 -0
- package/dist/a2a/a2a-client.d.ts +114 -0
- package/dist/a2a/a2a-client.d.ts.map +1 -0
- package/dist/a2a/a2a-client.js +405 -0
- package/dist/a2a/a2a-client.js.map +1 -0
- package/dist/a2a/a2a-event.d.ts +25 -0
- package/dist/a2a/a2a-event.d.ts.map +1 -0
- package/dist/a2a/a2a-event.js +9 -0
- package/dist/a2a/a2a-event.js.map +1 -0
- package/dist/a2a/a2a-job.d.ts +58 -0
- package/dist/a2a/a2a-job.d.ts.map +1 -0
- package/dist/a2a/a2a-job.js +264 -0
- package/dist/a2a/a2a-job.js.map +1 -0
- package/dist/a2a/a2a-stream.d.ts +39 -0
- package/dist/a2a/a2a-stream.d.ts.map +1 -0
- package/dist/a2a/a2a-stream.js +290 -0
- package/dist/a2a/a2a-stream.js.map +1 -0
- package/dist/a2a/errors.d.ts +29 -0
- package/dist/a2a/errors.d.ts.map +1 -0
- package/dist/a2a/errors.js +48 -0
- package/dist/a2a/errors.js.map +1 -0
- package/dist/a2a/index.d.ts +12 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +11 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/a2a/producer/auth-filter.d.ts +34 -0
- package/dist/a2a/producer/auth-filter.d.ts.map +1 -0
- package/dist/a2a/producer/auth-filter.js +39 -0
- package/dist/a2a/producer/auth-filter.js.map +1 -0
- package/dist/a2a/producer/card-builder.d.ts +59 -0
- package/dist/a2a/producer/card-builder.d.ts.map +1 -0
- package/dist/a2a/producer/card-builder.js +59 -0
- package/dist/a2a/producer/card-builder.js.map +1 -0
- package/dist/a2a/producer/dispatcher.d.ts +276 -0
- package/dist/a2a/producer/dispatcher.d.ts.map +1 -0
- package/dist/a2a/producer/dispatcher.js +896 -0
- package/dist/a2a/producer/dispatcher.js.map +1 -0
- package/dist/a2a/producer/index.d.ts +26 -0
- package/dist/a2a/producer/index.d.ts.map +1 -0
- package/dist/a2a/producer/index.js +23 -0
- package/dist/a2a/producer/index.js.map +1 -0
- package/dist/a2a/producer/mount.d.ts +75 -0
- package/dist/a2a/producer/mount.d.ts.map +1 -0
- package/dist/a2a/producer/mount.js +422 -0
- package/dist/a2a/producer/mount.js.map +1 -0
- package/dist/a2a/producer/public-url-cache.d.ts +73 -0
- package/dist/a2a/producer/public-url-cache.d.ts.map +1 -0
- package/dist/a2a/producer/public-url-cache.js +0 -0
- package/dist/a2a/producer/public-url-cache.js.map +1 -0
- package/dist/a2a/producer/registry.d.ts +138 -0
- package/dist/a2a/producer/registry.d.ts.map +1 -0
- package/dist/a2a/producer/registry.js +117 -0
- package/dist/a2a/producer/registry.js.map +1 -0
- package/dist/a2a/producer/sse-emitter.d.ts +85 -0
- package/dist/a2a/producer/sse-emitter.d.ts.map +1 -0
- package/dist/a2a/producer/sse-emitter.js +405 -0
- package/dist/a2a/producer/sse-emitter.js.map +1 -0
- package/dist/a2a/producer/state-translator.d.ts +63 -0
- package/dist/a2a/producer/state-translator.d.ts.map +1 -0
- package/dist/a2a/producer/state-translator.js +108 -0
- package/dist/a2a/producer/state-translator.js.map +1 -0
- package/dist/a2a/producer/task-store.d.ts +128 -0
- package/dist/a2a/producer/task-store.d.ts.map +1 -0
- package/dist/a2a/producer/task-store.js +128 -0
- package/dist/a2a/producer/task-store.js.map +1 -0
- package/dist/agent.d.ts +99 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +754 -19
- package/dist/agent.js.map +1 -1
- package/dist/api-runtime.d.ts +25 -0
- package/dist/api-runtime.d.ts.map +1 -1
- package/dist/api-runtime.js +75 -2
- package/dist/api-runtime.js.map +1 -1
- package/dist/claim-dispatcher.d.ts +126 -0
- package/dist/claim-dispatcher.d.ts.map +1 -0
- package/dist/claim-dispatcher.js +478 -0
- package/dist/claim-dispatcher.js.map +1 -0
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +33 -6
- package/dist/express.js.map +1 -1
- package/dist/inbound-job-dispatch.d.ts +105 -0
- package/dist/inbound-job-dispatch.d.ts.map +1 -0
- package/dist/inbound-job-dispatch.js +335 -0
- package/dist/inbound-job-dispatch.js.map +1 -0
- package/dist/index.d.ts +40 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -3
- package/dist/index.js.map +1 -1
- package/dist/job-context.d.ts +107 -0
- package/dist/job-context.d.ts.map +1 -0
- package/dist/job-context.js +95 -0
- package/dist/job-context.js.map +1 -0
- package/dist/jobs-cancel-route.d.ts +36 -0
- package/dist/jobs-cancel-route.d.ts.map +1 -0
- package/dist/jobs-cancel-route.js +60 -0
- package/dist/jobs-cancel-route.js.map +1 -0
- package/dist/jobs-helper-tools.d.ts +48 -0
- package/dist/jobs-helper-tools.d.ts.map +1 -0
- package/dist/jobs-helper-tools.js +133 -0
- package/dist/jobs-helper-tools.js.map +1 -0
- package/dist/llm-agent.d.ts +62 -53
- package/dist/llm-agent.d.ts.map +1 -1
- package/dist/llm-agent.js +211 -292
- package/dist/llm-agent.js.map +1 -1
- package/dist/llm-provider.d.ts +11 -4
- package/dist/llm-provider.d.ts.map +1 -1
- package/dist/llm-provider.js +57 -4
- package/dist/llm-provider.js.map +1 -1
- package/dist/llm.d.ts +4 -1
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +7 -17
- package/dist/llm.js.map +1 -1
- package/dist/media/resolver.d.ts.map +1 -1
- package/dist/media/resolver.js +3 -2
- package/dist/media/resolver.js.map +1 -1
- package/dist/mesh-job-submitter.d.ts +83 -0
- package/dist/mesh-job-submitter.d.ts.map +1 -0
- package/dist/mesh-job-submitter.js +143 -0
- package/dist/mesh-job-submitter.js.map +1 -0
- package/dist/provider-handlers/gemini-handler.js +5 -0
- package/dist/provider-handlers/gemini-handler.js.map +1 -1
- package/dist/proxy.d.ts +40 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +375 -2
- package/dist/proxy.js.map +1 -1
- package/dist/resolver-meshjob.d.ts +170 -0
- package/dist/resolver-meshjob.d.ts.map +1 -0
- package/dist/resolver-meshjob.js +159 -0
- package/dist/resolver-meshjob.js.map +1 -0
- package/dist/route.d.ts +4 -0
- package/dist/route.d.ts.map +1 -1
- package/dist/route.js.map +1 -1
- package/dist/schema-normalize.d.ts +62 -0
- package/dist/schema-normalize.d.ts.map +1 -0
- package/dist/schema-normalize.js +128 -0
- package/dist/schema-normalize.js.map +1 -0
- package/dist/sse-stream.d.ts +44 -0
- package/dist/sse-stream.d.ts.map +1 -0
- package/dist/sse-stream.js +173 -0
- package/dist/sse-stream.js.map +1 -0
- package/dist/tool-worker-entry.d.ts +21 -0
- package/dist/tool-worker-entry.d.ts.map +1 -0
- package/dist/tool-worker-entry.js +162 -0
- package/dist/tool-worker-entry.js.map +1 -0
- package/dist/tool-worker-pool.d.ts +49 -0
- package/dist/tool-worker-pool.d.ts.map +1 -0
- package/dist/tool-worker-pool.js +272 -0
- package/dist/tool-worker-pool.js.map +1 -0
- package/dist/types.d.ts +351 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for PR #938 W2 — race window in `ApiRuntime.start()`.
|
|
3
|
+
*
|
|
4
|
+
* `start()` does async work (TLS prep, tracing init) between the moment
|
|
5
|
+
* `scheduleStart()` flips `this.starting = true` and the moment
|
|
6
|
+
* `this.handle = startAgent(spec)` lands. A `mesh.a2a.mount(...)` fired
|
|
7
|
+
* during that gap was previously dropped on the floor:
|
|
8
|
+
*
|
|
9
|
+
* - `pushSurfacesUpdate()` early-returned on `!this.handle`
|
|
10
|
+
* - The startup-time spec was already built (snapshot of the registry
|
|
11
|
+
* BEFORE the deferred mount landed), so `startAgent(spec)` registered
|
|
12
|
+
* a stale surfaces[] payload
|
|
13
|
+
*
|
|
14
|
+
* The fix: `pushSurfacesUpdate()` sets a `pendingSurfacesPush` flag when
|
|
15
|
+
* `start()` is in flight (handle still null, `starting === true`).
|
|
16
|
+
* `start()` flushes the flag right after `this.handle = startAgent(spec)`.
|
|
17
|
+
* Smart-diffed inside the Rust runtime so the redundant push is a no-op
|
|
18
|
+
* when the snapshot already captured the mount.
|
|
19
|
+
*
|
|
20
|
+
* We mock `@mcpmesh/core` so this test never binds the real napi runtime,
|
|
21
|
+
* and we mock `prepareTls`/`initTracing` so `start()` doesn't touch the
|
|
22
|
+
* filesystem or Redis. The race fixture introduces a controlled
|
|
23
|
+
* `setImmediate` gap inside the mocked `initTracing` so we can fire
|
|
24
|
+
* `pushSurfacesUpdate()` at the exact race window.
|
|
25
|
+
*/
|
|
26
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
27
|
+
// ─── Mock @mcpmesh/core BEFORE importing api-runtime ────────────────────
|
|
28
|
+
const updateSurfacesSpy = vi.fn().mockResolvedValue(true);
|
|
29
|
+
const startAgentSpy = vi.fn();
|
|
30
|
+
const nextEventBlocker = new Promise(() => { }); // never resolves
|
|
31
|
+
vi.mock("@mcpmesh/core", async (importOriginal) => {
|
|
32
|
+
const actual = await importOriginal();
|
|
33
|
+
return {
|
|
34
|
+
...actual,
|
|
35
|
+
startAgent: (spec) => startAgentSpy(spec),
|
|
36
|
+
autoDetectIp: () => "127.0.0.1",
|
|
37
|
+
resolveConfig: (key, fallback) => {
|
|
38
|
+
// Minimal config resolution — return fallback or null for everything
|
|
39
|
+
// so `start()` proceeds with defaults.
|
|
40
|
+
if (key === "agent_name")
|
|
41
|
+
return "test-api";
|
|
42
|
+
return fallback ?? null;
|
|
43
|
+
},
|
|
44
|
+
resolveConfigInt: (_key, fallback) => fallback ?? null,
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
// Mock tls-config so prepareTls/cleanupTls don't touch the filesystem.
|
|
48
|
+
vi.mock("../tls-config.js", () => ({
|
|
49
|
+
getTlsConfigCached: () => ({ enabled: false }),
|
|
50
|
+
prepareTls: vi.fn(),
|
|
51
|
+
cleanupTls: vi.fn(),
|
|
52
|
+
}));
|
|
53
|
+
// Mock tracing so initTracing doesn't try to bind Redis. Crucially, we
|
|
54
|
+
// inject a `setImmediate` boundary INSIDE initTracing so the test can
|
|
55
|
+
// schedule a `pushSurfacesUpdate()` call at the precise race window —
|
|
56
|
+
// after `scheduleStart` flips `this.starting = true` but before
|
|
57
|
+
// `this.handle = startAgent(spec)` runs.
|
|
58
|
+
let initTracingResolve = null;
|
|
59
|
+
vi.mock("../tracing.js", () => ({
|
|
60
|
+
initTracing: vi.fn(async () => {
|
|
61
|
+
// Park here — the test resolves us once it has fired the racing
|
|
62
|
+
// `pushSurfacesUpdate()`. This deterministically holds the gap
|
|
63
|
+
// open instead of relying on real-world async timing.
|
|
64
|
+
await new Promise((resolve) => {
|
|
65
|
+
initTracingResolve = resolve;
|
|
66
|
+
});
|
|
67
|
+
}),
|
|
68
|
+
}));
|
|
69
|
+
import { ApiRuntime } from "../api-runtime.js";
|
|
70
|
+
import { A2AProducerRegistry } from "../a2a/producer/registry.js";
|
|
71
|
+
import { RouteRegistry } from "../route.js";
|
|
72
|
+
describe("ApiRuntime — pushSurfacesUpdate race window (#938 W2)", () => {
|
|
73
|
+
let sigintBefore;
|
|
74
|
+
let sigtermBefore;
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
sigintBefore = process.listeners("SIGINT");
|
|
77
|
+
sigintBefore = [...sigintBefore];
|
|
78
|
+
sigtermBefore = process.listeners("SIGTERM");
|
|
79
|
+
sigtermBefore = [...sigtermBefore];
|
|
80
|
+
A2AProducerRegistry.reset();
|
|
81
|
+
RouteRegistry.reset();
|
|
82
|
+
updateSurfacesSpy.mockClear();
|
|
83
|
+
startAgentSpy.mockReset();
|
|
84
|
+
initTracingResolve = null;
|
|
85
|
+
// Build a stub handle that captures updateSurfaces calls. nextEvent
|
|
86
|
+
// returns a never-resolving promise so the event loop parks
|
|
87
|
+
// immediately — we don't exercise it here.
|
|
88
|
+
startAgentSpy.mockImplementation(() => ({
|
|
89
|
+
updateSurfaces: updateSurfacesSpy,
|
|
90
|
+
updatePort: vi.fn().mockResolvedValue(true),
|
|
91
|
+
updateTools: vi.fn().mockResolvedValue(true),
|
|
92
|
+
nextEvent: () => nextEventBlocker,
|
|
93
|
+
shutdown: vi.fn().mockResolvedValue(undefined),
|
|
94
|
+
isShutdownRequested: () => false,
|
|
95
|
+
}));
|
|
96
|
+
// Reset the singleton so each test gets a clean ApiRuntime.
|
|
97
|
+
ApiRuntime.reset();
|
|
98
|
+
});
|
|
99
|
+
afterEach(() => {
|
|
100
|
+
// Unblock any parked initTracing in case a test bailed early.
|
|
101
|
+
if (initTracingResolve) {
|
|
102
|
+
initTracingResolve();
|
|
103
|
+
}
|
|
104
|
+
ApiRuntime.reset();
|
|
105
|
+
// Strip signal listeners we registered (see snapshot in beforeEach).
|
|
106
|
+
const currentSigint = process.listeners("SIGINT");
|
|
107
|
+
for (const l of currentSigint) {
|
|
108
|
+
if (!sigintBefore.includes(l)) {
|
|
109
|
+
process.removeListener("SIGINT", l);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const currentSigterm = process.listeners("SIGTERM");
|
|
113
|
+
for (const l of currentSigterm) {
|
|
114
|
+
if (!sigtermBefore.includes(l)) {
|
|
115
|
+
process.removeListener("SIGTERM", l);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
it("flushes a pushSurfacesUpdate fired during the start() async gap", async () => {
|
|
120
|
+
const runtime = ApiRuntime.getInstance();
|
|
121
|
+
// Kick off start(). It will park inside the mocked initTracing,
|
|
122
|
+
// holding the race window open until we resolve `initTracingResolve`.
|
|
123
|
+
const startPromise = runtime.start();
|
|
124
|
+
// Yield the event loop so start() advances past `this.starting = true`
|
|
125
|
+
// and into the `await initTracing(...)` await point.
|
|
126
|
+
await new Promise((r) => setImmediate(r));
|
|
127
|
+
// Sanity: handle still null (start is parked inside initTracing),
|
|
128
|
+
// and startAgent has NOT been called yet.
|
|
129
|
+
expect(startAgentSpy).not.toHaveBeenCalled();
|
|
130
|
+
// Simulate a deferred mount landing in the race window — register
|
|
131
|
+
// a surface in the producer registry, then fire pushSurfacesUpdate.
|
|
132
|
+
A2AProducerRegistry.getInstance().register({
|
|
133
|
+
path: "/agents/late",
|
|
134
|
+
skillId: "late-skill",
|
|
135
|
+
skillName: "Late Skill",
|
|
136
|
+
description: "",
|
|
137
|
+
tags: [],
|
|
138
|
+
dependencies: [],
|
|
139
|
+
auth: "",
|
|
140
|
+
routeId: "route-late",
|
|
141
|
+
});
|
|
142
|
+
runtime.pushSurfacesUpdate();
|
|
143
|
+
// Without the W2 fix, this push is silently dropped:
|
|
144
|
+
// - `handle === null` so the early-return triggers
|
|
145
|
+
// - `pendingSurfacesPush` doesn't exist, so no flush
|
|
146
|
+
//
|
|
147
|
+
// With the fix, the push is queued via `pendingSurfacesPush = true`
|
|
148
|
+
// and replayed after `this.handle = startAgent(spec)` is set.
|
|
149
|
+
// Unblock initTracing so start() proceeds to startAgent + flush.
|
|
150
|
+
initTracingResolve();
|
|
151
|
+
initTracingResolve = null;
|
|
152
|
+
await startPromise;
|
|
153
|
+
// The startup-time snapshot would have included the late-mounted
|
|
154
|
+
// surface (it landed BEFORE startAgent was called in our fixture
|
|
155
|
+
// here — the gap is between scheduleStart and startAgent). So the
|
|
156
|
+
// initial startAgent call already advertises the late surface AND
|
|
157
|
+
// the W2 flush replays it (smart-diffed by the Rust runtime).
|
|
158
|
+
//
|
|
159
|
+
// The behavior we assert is the FLUSH — `updateSurfaces` is called
|
|
160
|
+
// exactly once after the handle is set, with the late surface in
|
|
161
|
+
// the payload.
|
|
162
|
+
expect(updateSurfacesSpy).toHaveBeenCalledTimes(1);
|
|
163
|
+
const [agentType, surfacesJson] = updateSurfacesSpy.mock.calls[0];
|
|
164
|
+
expect(agentType).toBe("a2a");
|
|
165
|
+
const parsed = JSON.parse(surfacesJson);
|
|
166
|
+
expect(parsed).toHaveLength(1);
|
|
167
|
+
expect(parsed[0]).toMatchObject({
|
|
168
|
+
path: "/agents/late",
|
|
169
|
+
skill_id: "late-skill",
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
it("does NOT flush when no pushSurfacesUpdate fired during the gap", async () => {
|
|
173
|
+
const runtime = ApiRuntime.getInstance();
|
|
174
|
+
const startPromise = runtime.start();
|
|
175
|
+
await new Promise((r) => setImmediate(r));
|
|
176
|
+
// No racing push — just let start() complete.
|
|
177
|
+
initTracingResolve();
|
|
178
|
+
initTracingResolve = null;
|
|
179
|
+
await startPromise;
|
|
180
|
+
// `pendingSurfacesPush` stayed false, so no flush after handle is set.
|
|
181
|
+
expect(updateSurfacesSpy).not.toHaveBeenCalled();
|
|
182
|
+
});
|
|
183
|
+
it("is a no-op when called BEFORE scheduleStart (starting=false, handle=null)", () => {
|
|
184
|
+
const runtime = ApiRuntime.getInstance();
|
|
185
|
+
// Cold runtime — neither started nor starting. Push is a true no-op:
|
|
186
|
+
// the eventual `start()` will pick up the registry state via
|
|
187
|
+
// `buildAgentSpecContribution()` at startup time.
|
|
188
|
+
runtime.pushSurfacesUpdate();
|
|
189
|
+
expect(updateSurfacesSpy).not.toHaveBeenCalled();
|
|
190
|
+
expect(startAgentSpy).not.toHaveBeenCalled();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
//# sourceMappingURL=api-runtime-race.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-runtime-race.spec.js","sourceRoot":"","sources":["../../src/__tests__/api-runtime-race.spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,2EAA2E;AAC3E,MAAM,iBAAiB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC1D,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAC9B,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAQ,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB;AAExE,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAChD,MAAM,MAAM,GAAG,MAAM,cAAc,EAAkC,CAAC;IACtE,OAAO;QACL,GAAG,MAAM;QACT,UAAU,EAAE,CAAC,IAAa,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC;QAClD,YAAY,EAAE,GAAG,EAAE,CAAC,WAAW;QAC/B,aAAa,EAAE,CAAC,GAAW,EAAE,QAAiB,EAAE,EAAE;YAChD,qEAAqE;YACrE,uCAAuC;YACvC,IAAI,GAAG,KAAK,YAAY;gBAAE,OAAO,UAAU,CAAC;YAC5C,OAAO,QAAQ,IAAI,IAAI,CAAC;QAC1B,CAAC;QACD,gBAAgB,EAAE,CAAC,IAAY,EAAE,QAAiB,EAAE,EAAE,CAAC,QAAQ,IAAI,IAAI;KACxE,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,uEAAuE;AACvE,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9C,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;CACpB,CAAC,CAAC,CAAC;AAEJ,uEAAuE;AACvE,sEAAsE;AACtE,sEAAsE;AACtE,gEAAgE;AAChE,yCAAyC;AACzC,IAAI,kBAAkB,GAAwB,IAAI,CAAC;AACnD,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9B,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;QAC5B,gEAAgE;QAChE,+DAA+D;QAC/D,sDAAsD;QACtD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,kBAAkB,GAAG,OAAO,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,QAAQ,CAAC,uDAAuD,EAAE,GAAG,EAAE;IAQrE,IAAI,YAA8B,CAAC;IACnC,IAAI,aAA+B,CAAC;IAEpC,UAAU,CAAC,GAAG,EAAE;QACd,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAgC,CAAC;QAC1E,YAAY,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;QACjC,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAgC,CAAC;QAC5E,aAAa,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC;QACnC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QAC5B,aAAa,CAAC,KAAK,EAAE,CAAC;QACtB,iBAAiB,CAAC,SAAS,EAAE,CAAC;QAC9B,aAAa,CAAC,SAAS,EAAE,CAAC;QAC1B,kBAAkB,GAAG,IAAI,CAAC;QAE1B,oEAAoE;QACpE,4DAA4D;QAC5D,2CAA2C;QAC3C,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC;YACtC,cAAc,EAAE,iBAAiB;YACjC,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAC3C,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAC5C,SAAS,EAAE,GAAG,EAAE,CAAC,gBAAgB;YACjC,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;YAC9C,mBAAmB,EAAE,GAAG,EAAE,CAAC,KAAK;SACjC,CAAC,CAAC,CAAC;QAEJ,4DAA4D;QAC5D,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,8DAA8D;QAC9D,IAAI,kBAAkB,EAAE,CAAC;YACvB,kBAAkB,EAAE,CAAC;QACvB,CAAC;QACD,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,qEAAqE;QACrE,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAgC,CAAC;QACjF,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;YAC9B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QACD,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAgC,CAAC;QACnF,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;YAC/B,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/B,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QAEzC,gEAAgE;QAChE,sEAAsE;QACtE,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAErC,uEAAuE;QACvE,qDAAqD;QACrD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1C,kEAAkE;QAClE,0CAA0C;QAC1C,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAE7C,kEAAkE;QAClE,oEAAoE;QACpE,mBAAmB,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC;YACzC,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,YAAY;YACvB,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,EAAE;YACR,YAAY,EAAE,EAAE;YAChB,IAAI,EAAE,EAAE;YACR,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAE7B,qDAAqD;QACrD,qDAAqD;QACrD,uDAAuD;QACvD,EAAE;QACF,oEAAoE;QACpE,8DAA8D;QAE9D,iEAAiE;QACjE,kBAAmB,EAAE,CAAC;QACtB,kBAAkB,GAAG,IAAI,CAAC;QAE1B,MAAM,YAAY,CAAC;QAEnB,iEAAiE;QACjE,iEAAiE;QACjE,kEAAkE;QAClE,kEAAkE;QAClE,8DAA8D;QAC9D,EAAE;QACF,mEAAmE;QACnE,iEAAiE;QACjE,eAAe;QACf,MAAM,CAAC,iBAAiB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAsB,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YAC9B,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,YAAY;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1C,8CAA8C;QAC9C,kBAAmB,EAAE,CAAC;QACtB,kBAAkB,GAAG,IAAI,CAAC;QAC1B,MAAM,YAAY,CAAC;QAEnB,uEAAuE;QACvE,MAAM,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QAEzC,qEAAqE;QACrE,6DAA6D;QAC7D,kDAAkD;QAClD,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAE7B,MAAM,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-dispatcher.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/claim-dispatcher.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for ClaimDispatcher (Phase 1 — MeshJob substrate).
|
|
3
|
+
*
|
|
4
|
+
* The dispatcher polls `POST /jobs/claim` periodically and dispatches
|
|
5
|
+
* claimed work via the local handler. Heavy on side effects, so tests
|
|
6
|
+
* use a stubbed `fetch` and a minimal handler — we exercise:
|
|
7
|
+
*
|
|
8
|
+
* - Empty-claim behaviour (HTTP 204 → backoff, no handler call).
|
|
9
|
+
* - Successful claim → handler invoked with payload, controller
|
|
10
|
+
* constructed via napi.
|
|
11
|
+
* - The claim-then-acquire ordering: even with an immediate claim,
|
|
12
|
+
* the dispatcher must hold a permit before issuing the POST so
|
|
13
|
+
* it never owns more jobs than it can run.
|
|
14
|
+
* - Stop semantics: a long-running handler doesn't block stop().
|
|
15
|
+
*
|
|
16
|
+
* The napi `JobController` constructor is real — it doesn't reach out
|
|
17
|
+
* to the registry until `complete()`/`updateProgress()` is called, so
|
|
18
|
+
* the test stays in-process.
|
|
19
|
+
*/
|
|
20
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
21
|
+
import { ClaimDispatcher } from "../claim-dispatcher.js";
|
|
22
|
+
import { getCurrentPropagatedHeaders } from "../proxy.js";
|
|
23
|
+
import * as inboundDispatch from "../inbound-job-dispatch.js";
|
|
24
|
+
// Mock @mcpmesh/core so the real JobController/withJobAsync don't
|
|
25
|
+
// actually try to reach the registry. The dispatcher uses `fetch`
|
|
26
|
+
// directly for /jobs/claim (mocked separately below).
|
|
27
|
+
vi.mock("@mcpmesh/core", async () => {
|
|
28
|
+
const actual = await vi.importActual("@mcpmesh/core");
|
|
29
|
+
return {
|
|
30
|
+
...actual,
|
|
31
|
+
// The dispatcher constructs JobController via makeJobController
|
|
32
|
+
// (which calls `new JobController(...)`). Replace with a stub so
|
|
33
|
+
// the constructor doesn't spawn the per-controller batching tick
|
|
34
|
+
// (which would keep the test process alive past the test).
|
|
35
|
+
JobController: class {
|
|
36
|
+
jobId;
|
|
37
|
+
constructor(jobId, _instanceId, _registryUrl) {
|
|
38
|
+
this.jobId = jobId;
|
|
39
|
+
}
|
|
40
|
+
isTerminal = vi.fn().mockResolvedValue(true);
|
|
41
|
+
complete = vi.fn().mockResolvedValue(undefined);
|
|
42
|
+
fail = vi.fn().mockResolvedValue(undefined);
|
|
43
|
+
updateProgress = vi.fn().mockResolvedValue(undefined);
|
|
44
|
+
},
|
|
45
|
+
// withJobAsync just runs the body without binding the Rust
|
|
46
|
+
// task-local — fine for a test.
|
|
47
|
+
withJobAsync: vi.fn(async (_jobId, _deadline, body) => body),
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
const originalFetch = globalThis.fetch;
|
|
51
|
+
describe("ClaimDispatcher", () => {
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
globalThis.fetch = vi.fn();
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
+
globalThis.fetch = originalFetch;
|
|
59
|
+
});
|
|
60
|
+
it("polls /jobs/claim and skips when registry returns 204 (no work)", async () => {
|
|
61
|
+
const fetchMock = globalThis.fetch;
|
|
62
|
+
fetchMock.mockResolvedValue({
|
|
63
|
+
status: 204,
|
|
64
|
+
json: async () => ({}),
|
|
65
|
+
});
|
|
66
|
+
const handler = vi.fn().mockResolvedValue("ok");
|
|
67
|
+
const d = new ClaimDispatcher("cap", "agent-instance", "http://reg", handler);
|
|
68
|
+
d.start();
|
|
69
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
70
|
+
await d.stop();
|
|
71
|
+
expect(fetchMock).toHaveBeenCalled();
|
|
72
|
+
expect(handler).not.toHaveBeenCalled();
|
|
73
|
+
// Check the URL + body the dispatcher used to claim.
|
|
74
|
+
const [url, init] = fetchMock.mock.calls[0];
|
|
75
|
+
expect(url).toBe("http://reg/jobs/claim");
|
|
76
|
+
expect(init.method).toBe("POST");
|
|
77
|
+
const body = JSON.parse(init.body);
|
|
78
|
+
expect(body.capability).toBe("cap");
|
|
79
|
+
expect(body.instance_id).toBe("agent-instance");
|
|
80
|
+
});
|
|
81
|
+
it("dispatches a claimed job to the handler with the submitted payload", async () => {
|
|
82
|
+
const fetchMock = globalThis.fetch;
|
|
83
|
+
let calls = 0;
|
|
84
|
+
fetchMock.mockImplementation(async () => {
|
|
85
|
+
calls += 1;
|
|
86
|
+
// First poll returns one claim; subsequent polls return empty
|
|
87
|
+
// so the dispatcher backs off and the test can stop cleanly.
|
|
88
|
+
if (calls === 1) {
|
|
89
|
+
return {
|
|
90
|
+
status: 200,
|
|
91
|
+
json: async () => ({
|
|
92
|
+
claimed: [
|
|
93
|
+
{
|
|
94
|
+
id: "job-uuid-1",
|
|
95
|
+
submitted_payload: { user_id: "u", n: 5 },
|
|
96
|
+
max_duration: 30,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return { status: 204, json: async () => ({}) };
|
|
103
|
+
});
|
|
104
|
+
const handler = vi.fn().mockResolvedValue({ done: true });
|
|
105
|
+
const d = new ClaimDispatcher("cap", "agent-instance", "http://reg", handler);
|
|
106
|
+
d.start();
|
|
107
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
108
|
+
await d.stop();
|
|
109
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
110
|
+
const [payload, ctrl] = handler.mock.calls[0];
|
|
111
|
+
expect(payload).toEqual({ user_id: "u", n: 5 });
|
|
112
|
+
expect(ctrl).toBeDefined();
|
|
113
|
+
// Stub controller exposes jobId.
|
|
114
|
+
expect(ctrl.jobId).toBe("job-uuid-1");
|
|
115
|
+
});
|
|
116
|
+
it("treats malformed claim responses as no work (no crash, no handler call)", async () => {
|
|
117
|
+
const fetchMock = globalThis.fetch;
|
|
118
|
+
fetchMock.mockResolvedValue({
|
|
119
|
+
status: 200,
|
|
120
|
+
json: async () => ({ claimed: "not-a-list" }),
|
|
121
|
+
});
|
|
122
|
+
const handler = vi.fn();
|
|
123
|
+
const d = new ClaimDispatcher("cap", "i", "http://r", handler);
|
|
124
|
+
d.start();
|
|
125
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
126
|
+
await d.stop();
|
|
127
|
+
expect(handler).not.toHaveBeenCalled();
|
|
128
|
+
});
|
|
129
|
+
it("filters out claimed entries without an id", async () => {
|
|
130
|
+
const fetchMock = globalThis.fetch;
|
|
131
|
+
let calls = 0;
|
|
132
|
+
fetchMock.mockImplementation(async () => {
|
|
133
|
+
calls += 1;
|
|
134
|
+
if (calls === 1) {
|
|
135
|
+
return {
|
|
136
|
+
status: 200,
|
|
137
|
+
json: async () => ({
|
|
138
|
+
claimed: [
|
|
139
|
+
{ not_an_id: true },
|
|
140
|
+
{ id: "" },
|
|
141
|
+
{ id: "real-job", submitted_payload: {} },
|
|
142
|
+
],
|
|
143
|
+
}),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return { status: 204, json: async () => ({}) };
|
|
147
|
+
});
|
|
148
|
+
const handler = vi.fn().mockResolvedValue("done");
|
|
149
|
+
const d = new ClaimDispatcher("cap", "i", "http://r", handler);
|
|
150
|
+
d.start();
|
|
151
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
152
|
+
await d.stop();
|
|
153
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
154
|
+
expect(handler.mock.calls[0][1].jobId).toBe("real-job");
|
|
155
|
+
});
|
|
156
|
+
it("seeds the propagated-headers ALS with x-mesh-job-id (and x-mesh-timeout when present)", async () => {
|
|
157
|
+
// Verifies follow-up #2: claim-path dispatches must seed the
|
|
158
|
+
// propagated-headers AsyncLocalStorage so outbound calls made by
|
|
159
|
+
// the handler continue the submitter's trace tree (Python parity
|
|
160
|
+
// — see `_mcp_mesh.engine.claim_dispatcher.PythonClaimDispatcher
|
|
161
|
+
// ._dispatch`'s `TraceContext.set_propagated_headers` block).
|
|
162
|
+
const fetchMock = globalThis.fetch;
|
|
163
|
+
let calls = 0;
|
|
164
|
+
fetchMock.mockImplementation(async () => {
|
|
165
|
+
calls += 1;
|
|
166
|
+
if (calls === 1) {
|
|
167
|
+
return {
|
|
168
|
+
status: 200,
|
|
169
|
+
json: async () => ({
|
|
170
|
+
claimed: [
|
|
171
|
+
{
|
|
172
|
+
id: "job-trace-1",
|
|
173
|
+
submitted_payload: { foo: "bar" },
|
|
174
|
+
max_duration: 45,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return { status: 204, json: async () => ({}) };
|
|
181
|
+
});
|
|
182
|
+
let observed = null;
|
|
183
|
+
const handler = vi.fn(async () => {
|
|
184
|
+
// Snapshot the ALS view from inside the user handler — exactly
|
|
185
|
+
// where outbound proxy calls would read it.
|
|
186
|
+
observed = { ...getCurrentPropagatedHeaders() };
|
|
187
|
+
return { ok: true };
|
|
188
|
+
});
|
|
189
|
+
const d = new ClaimDispatcher("cap-trace", "agent-1", "http://reg", handler);
|
|
190
|
+
d.start();
|
|
191
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
192
|
+
await d.stop();
|
|
193
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
194
|
+
expect(observed).not.toBeNull();
|
|
195
|
+
expect(observed["x-mesh-job-id"]).toBe("job-trace-1");
|
|
196
|
+
expect(observed["x-mesh-timeout"]).toBe("45");
|
|
197
|
+
});
|
|
198
|
+
it("omits x-mesh-timeout when claim has no max_duration", async () => {
|
|
199
|
+
// Defensive: a claim without max_duration must not seed an empty
|
|
200
|
+
// / zero-valued timeout header (downstream parsers would reject it).
|
|
201
|
+
const fetchMock = globalThis.fetch;
|
|
202
|
+
let calls = 0;
|
|
203
|
+
fetchMock.mockImplementation(async () => {
|
|
204
|
+
calls += 1;
|
|
205
|
+
if (calls === 1) {
|
|
206
|
+
return {
|
|
207
|
+
status: 200,
|
|
208
|
+
json: async () => ({
|
|
209
|
+
claimed: [{ id: "job-no-timeout", submitted_payload: {} }],
|
|
210
|
+
}),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return { status: 204, json: async () => ({}) };
|
|
214
|
+
});
|
|
215
|
+
let observed = null;
|
|
216
|
+
const handler = vi.fn(async () => {
|
|
217
|
+
observed = { ...getCurrentPropagatedHeaders() };
|
|
218
|
+
return null;
|
|
219
|
+
});
|
|
220
|
+
const d = new ClaimDispatcher("cap-no-timeout", "i", "http://r", handler);
|
|
221
|
+
d.start();
|
|
222
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
223
|
+
await d.stop();
|
|
224
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
225
|
+
expect(observed).not.toBeNull();
|
|
226
|
+
expect(observed["x-mesh-job-id"]).toBe("job-no-timeout");
|
|
227
|
+
expect(observed["x-mesh-timeout"]).toBeUndefined();
|
|
228
|
+
});
|
|
229
|
+
it("stop() closes the keep-alive http agent (no leaked sockets)", async () => {
|
|
230
|
+
// Verifies follow-up #3: each ClaimDispatcher owns an undici Agent
|
|
231
|
+
// for connection reuse on /jobs/claim polls; stop() must close
|
|
232
|
+
// it so long-lived test harnesses don't leak sockets across
|
|
233
|
+
// agent restarts.
|
|
234
|
+
const fetchMock = globalThis.fetch;
|
|
235
|
+
fetchMock.mockResolvedValue({
|
|
236
|
+
status: 204,
|
|
237
|
+
json: async () => ({}),
|
|
238
|
+
});
|
|
239
|
+
const d = new ClaimDispatcher("cap-stop", "i", "http://r", vi.fn());
|
|
240
|
+
// The Agent is private; reach in to verify close-state transitions.
|
|
241
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
242
|
+
const agent = d._httpAgent;
|
|
243
|
+
const closeSpy = vi.spyOn(agent, "close");
|
|
244
|
+
d.start();
|
|
245
|
+
await new Promise((r) => setTimeout(r, 30));
|
|
246
|
+
await d.stop();
|
|
247
|
+
// We invoke close() once from stop(); undici's DispatcherBase
|
|
248
|
+
// re-enters close(callback) internally, which the spy records as
|
|
249
|
+
// a second call. We only care that it was invoked (and that the
|
|
250
|
+
// agent is now in the closed state).
|
|
251
|
+
expect(closeSpy).toHaveBeenCalled();
|
|
252
|
+
expect(agent.closed || agent.destroyed).toBe(true);
|
|
253
|
+
});
|
|
254
|
+
it("stop() drains in-flight handlers before closing the keep-alive pool", async () => {
|
|
255
|
+
// Verifies the F7 follow-up: stop() must await any handler
|
|
256
|
+
// dispatches that are still mid-fetch before it tears down the
|
|
257
|
+
// shared `_httpAgent`. Without the drain, controller.complete /
|
|
258
|
+
// controller.fail HTTP calls would race with Agent.close() and
|
|
259
|
+
// surface as cryptic socket-closed errors — worse, the terminal
|
|
260
|
+
// delta might never reach the registry, leaving the row stuck.
|
|
261
|
+
const fetchMock = globalThis.fetch;
|
|
262
|
+
let calls = 0;
|
|
263
|
+
fetchMock.mockImplementation(async () => {
|
|
264
|
+
calls += 1;
|
|
265
|
+
if (calls === 1) {
|
|
266
|
+
return {
|
|
267
|
+
status: 200,
|
|
268
|
+
json: async () => ({
|
|
269
|
+
claimed: [{ id: "long", submitted_payload: {} }],
|
|
270
|
+
}),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return { status: 204, json: async () => ({}) };
|
|
274
|
+
});
|
|
275
|
+
let resolveHandler;
|
|
276
|
+
let handlerObservedFinish = false;
|
|
277
|
+
const handler = vi.fn(() => new Promise((resolve) => {
|
|
278
|
+
resolveHandler = () => {
|
|
279
|
+
handlerObservedFinish = true;
|
|
280
|
+
resolve("done");
|
|
281
|
+
};
|
|
282
|
+
}));
|
|
283
|
+
const d = new ClaimDispatcher("cap", "i", "http://r", handler);
|
|
284
|
+
// The Agent is private; verify close ordering relative to handler
|
|
285
|
+
// resolution. eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
286
|
+
const httpAgent = d._httpAgent;
|
|
287
|
+
let closedAt = 0;
|
|
288
|
+
const closeSpy = vi.spyOn(httpAgent, "close").mockImplementation(async () => {
|
|
289
|
+
closedAt = Date.now();
|
|
290
|
+
});
|
|
291
|
+
d.start();
|
|
292
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
293
|
+
// Kick off stop(); resolve the handler ~20ms later.
|
|
294
|
+
const stopStart = Date.now();
|
|
295
|
+
const stopPromise = d.stop();
|
|
296
|
+
let resolvedAt = 0;
|
|
297
|
+
setTimeout(() => {
|
|
298
|
+
resolvedAt = Date.now();
|
|
299
|
+
resolveHandler();
|
|
300
|
+
}, 20);
|
|
301
|
+
await stopPromise;
|
|
302
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
303
|
+
expect(handlerObservedFinish).toBe(true);
|
|
304
|
+
// The keep-alive pool must close STRICTLY AFTER the handler
|
|
305
|
+
// resolved — that's the whole point of the drain.
|
|
306
|
+
expect(closeSpy).toHaveBeenCalled();
|
|
307
|
+
expect(resolvedAt).toBeGreaterThan(0);
|
|
308
|
+
expect(closedAt).toBeGreaterThanOrEqual(resolvedAt);
|
|
309
|
+
// Sanity: stop() should still be quick — the bounded timeout is
|
|
310
|
+
// 30s default, but we resolved at 20ms, so total wall < 1s.
|
|
311
|
+
expect(Date.now() - stopStart).toBeLessThan(1000);
|
|
312
|
+
closeSpy.mockRestore();
|
|
313
|
+
});
|
|
314
|
+
it("stop(timeoutMs=0) skips the drain when the caller asks for an immediate close", async () => {
|
|
315
|
+
// Defensive: the bounded-drain default is 30s, but the caller can
|
|
316
|
+
// pass `0` to force-close (e.g. tests that stub a long-running
|
|
317
|
+
// handler and don't want to wait for it). Verify the path doesn't
|
|
318
|
+
// hang on the in-flight handler.
|
|
319
|
+
const fetchMock = globalThis.fetch;
|
|
320
|
+
let calls = 0;
|
|
321
|
+
fetchMock.mockImplementation(async () => {
|
|
322
|
+
calls += 1;
|
|
323
|
+
if (calls === 1) {
|
|
324
|
+
return {
|
|
325
|
+
status: 200,
|
|
326
|
+
json: async () => ({
|
|
327
|
+
claimed: [{ id: "never-finishes", submitted_payload: {} }],
|
|
328
|
+
}),
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return { status: 204, json: async () => ({}) };
|
|
332
|
+
});
|
|
333
|
+
let resolveHandler;
|
|
334
|
+
const handler = vi.fn(() => new Promise((resolve) => {
|
|
335
|
+
resolveHandler = () => resolve("done");
|
|
336
|
+
}));
|
|
337
|
+
const d = new ClaimDispatcher("cap", "i", "http://r", handler);
|
|
338
|
+
d.start();
|
|
339
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
340
|
+
const t0 = Date.now();
|
|
341
|
+
await d.stop(0);
|
|
342
|
+
expect(Date.now() - t0).toBeLessThan(500);
|
|
343
|
+
// Cleanup: resolve the dangling handler so it doesn't keep the
|
|
344
|
+
// event loop alive past the test.
|
|
345
|
+
resolveHandler();
|
|
346
|
+
});
|
|
347
|
+
it("posts a `failed` /jobs/batch delta when JobController construction throws (W2)", async () => {
|
|
348
|
+
// Review finding W2: previously a `console.warn` + early return left
|
|
349
|
+
// the registry believing this replica owned the job until lease
|
|
350
|
+
// expiry, leaving the row stuck in `working`. The fix is to fire a
|
|
351
|
+
// POST /jobs/batch failed delta directly (bypassing the controller
|
|
352
|
+
// we couldn't construct) so the row flips terminal immediately and
|
|
353
|
+
// unblocks retry.
|
|
354
|
+
const ctorSpy = vi
|
|
355
|
+
.spyOn(inboundDispatch, "makeJobController")
|
|
356
|
+
.mockImplementation(() => {
|
|
357
|
+
throw new Error("boom: napi binding refused");
|
|
358
|
+
});
|
|
359
|
+
const fetchMock = globalThis.fetch;
|
|
360
|
+
let calls = 0;
|
|
361
|
+
const claimUrl = "http://reg/jobs/claim";
|
|
362
|
+
const batchUrl = "http://reg/jobs/batch";
|
|
363
|
+
fetchMock.mockImplementation(async (url) => {
|
|
364
|
+
calls += 1;
|
|
365
|
+
if (url === claimUrl && calls === 1) {
|
|
366
|
+
return {
|
|
367
|
+
status: 200,
|
|
368
|
+
json: async () => ({
|
|
369
|
+
claimed: [
|
|
370
|
+
{
|
|
371
|
+
id: "job-broken-ctor",
|
|
372
|
+
submitted_payload: { x: 1 },
|
|
373
|
+
},
|
|
374
|
+
],
|
|
375
|
+
}),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
if (url === batchUrl) {
|
|
379
|
+
return { status: 200, json: async () => ({}) };
|
|
380
|
+
}
|
|
381
|
+
return { status: 204, json: async () => ({}) };
|
|
382
|
+
});
|
|
383
|
+
const handler = vi.fn();
|
|
384
|
+
const d = new ClaimDispatcher("cap-broken", "agent-x", "http://reg", handler);
|
|
385
|
+
d.start();
|
|
386
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
387
|
+
await d.stop();
|
|
388
|
+
// Handler must NOT have been invoked — the dispatcher bailed before
|
|
389
|
+
// calling it because we couldn't build a controller.
|
|
390
|
+
expect(handler).not.toHaveBeenCalled();
|
|
391
|
+
// The fail-fast path must have POSTed a `failed` delta to /jobs/batch.
|
|
392
|
+
const batchCall = fetchMock.mock.calls.find((call) => call[0] === batchUrl);
|
|
393
|
+
expect(batchCall, "expected a POST /jobs/batch fail-fast call").toBeDefined();
|
|
394
|
+
const init = batchCall[1];
|
|
395
|
+
expect(init.method).toBe("POST");
|
|
396
|
+
const body = JSON.parse(init.body);
|
|
397
|
+
expect(body.instance_id).toBe("agent-x");
|
|
398
|
+
expect(body.deltas).toHaveLength(1);
|
|
399
|
+
const delta = body.deltas[0];
|
|
400
|
+
expect(delta.id).toBe("job-broken-ctor");
|
|
401
|
+
expect(delta.status).toBe("failed");
|
|
402
|
+
expect(typeof delta.error).toBe("string");
|
|
403
|
+
expect(delta.error).toContain("controller construction failed");
|
|
404
|
+
expect(delta.error).toContain("boom: napi binding refused");
|
|
405
|
+
ctorSpy.mockRestore();
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
//# sourceMappingURL=claim-dispatcher.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-dispatcher.spec.js","sourceRoot":"","sources":["../../src/__tests__/claim-dispatcher.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-job-dispatch.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/inbound-job-dispatch.spec.ts"],"names":[],"mappings":""}
|