Skip to content

Commit d27d7ba

Browse files
committed
perf(test): narrow gateway context reload coverage
1 parent f650d64 commit d27d7ba

3 files changed

Lines changed: 74 additions & 67 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { resolveGlobalSingleton } from "../shared/global-singleton.js";
2+
import type { GatewayRequestContext } from "./server-methods/types.js";
3+
4+
const FALLBACK_GATEWAY_CONTEXT_STATE_KEY: unique symbol = Symbol.for(
5+
"openclaw.fallbackGatewayContextState",
6+
);
7+
8+
type FallbackGatewayContextState = {
9+
context: GatewayRequestContext | undefined;
10+
resolveContext: (() => GatewayRequestContext | undefined) | undefined;
11+
};
12+
13+
const getFallbackGatewayContextState = () =>
14+
resolveGlobalSingleton<FallbackGatewayContextState>(FALLBACK_GATEWAY_CONTEXT_STATE_KEY, () => ({
15+
context: undefined,
16+
resolveContext: undefined,
17+
}));
18+
19+
/** Set the process fallback gateway context for channel adapters outside WS requests. */
20+
export function setFallbackGatewayContext(ctx: GatewayRequestContext): () => void {
21+
const fallbackGatewayContextState = getFallbackGatewayContextState();
22+
fallbackGatewayContextState.context = ctx;
23+
fallbackGatewayContextState.resolveContext = undefined;
24+
return () => {
25+
const currentFallbackGatewayContextState = getFallbackGatewayContextState();
26+
if (
27+
currentFallbackGatewayContextState.context === ctx &&
28+
currentFallbackGatewayContextState.resolveContext === undefined
29+
) {
30+
currentFallbackGatewayContextState.context = undefined;
31+
}
32+
};
33+
}
34+
35+
export function setFallbackGatewayContextResolver(
36+
resolveContext: () => GatewayRequestContext | undefined,
37+
): () => void {
38+
const fallbackGatewayContextState = getFallbackGatewayContextState();
39+
fallbackGatewayContextState.context = undefined;
40+
fallbackGatewayContextState.resolveContext = resolveContext;
41+
return () => {
42+
const currentFallbackGatewayContextState = getFallbackGatewayContextState();
43+
if (currentFallbackGatewayContextState.resolveContext === resolveContext) {
44+
currentFallbackGatewayContextState.context = undefined;
45+
currentFallbackGatewayContextState.resolveContext = undefined;
46+
}
47+
};
48+
}
49+
50+
/** Clear the fallback gateway context installed for non-WS dispatch paths. */
51+
export function clearFallbackGatewayContext(): void {
52+
const fallbackGatewayContextState = getFallbackGatewayContextState();
53+
fallbackGatewayContextState.context = undefined;
54+
fallbackGatewayContextState.resolveContext = undefined;
55+
}
56+
57+
export function getFallbackGatewayContext(): GatewayRequestContext | undefined {
58+
const fallbackGatewayContextState = getFallbackGatewayContextState();
59+
const resolved = fallbackGatewayContextState.resolveContext?.();
60+
return resolved ?? fallbackGatewayContextState.context;
61+
}

src/gateway/server-plugins.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,11 @@ async function createSubagentRuntime(
321321
return runtimeModule.createPluginRuntime({ allowGatewaySubagentBinding: true }).subagent;
322322
}
323323

324-
async function reloadServerPluginsModule(): Promise<ServerPluginsModule> {
324+
async function reloadFallbackGatewayContextModule() {
325+
// Existing runtimes retain the old module graph; only the process-global state owner
326+
// must reload to prove a restarted Gateway can replace their fallback context.
325327
vi.resetModules();
326-
return await import("./server-plugins.js");
328+
return await import("./server-plugin-fallback-context.js");
327329
}
328330

329331
function loadGatewayPluginsForTest(
@@ -1611,7 +1613,7 @@ describe("loadGatewayPlugins", () => {
16111613
await runtime.run({ sessionKey: "s-1", message: "hello" });
16121614
expect(getLastDispatchedContext()).toBe(staleContext);
16131615

1614-
const reloaded = await reloadServerPluginsModule();
1616+
const reloaded = await reloadFallbackGatewayContextModule();
16151617
const freshContext = createTestContext("fresh");
16161618
reloaded.setFallbackGatewayContext(freshContext);
16171619

src/gateway/server-plugins.ts

Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -29,70 +29,14 @@ import { resolveGlobalSingleton } from "../shared/global-singleton.js";
2929
import { resolveSafeTimeoutDelayMs } from "../utils/timer-delay.js";
3030
import { ADMIN_SCOPE, APPROVALS_SCOPE, WRITE_SCOPE } from "./method-scopes.js";
3131
import { normalizeOperatorScopeList, type OperatorScope } from "./operator-scopes.js";
32-
import type {
33-
GatewayRequestContext,
34-
GatewayRequestHandler,
35-
GatewayRequestOptions,
36-
} from "./server-methods/types.js";
37-
38-
const FALLBACK_GATEWAY_CONTEXT_STATE_KEY: unique symbol = Symbol.for(
39-
"openclaw.fallbackGatewayContextState",
40-
);
41-
42-
type FallbackGatewayContextState = {
43-
context: GatewayRequestContext | undefined;
44-
resolveContext: (() => GatewayRequestContext | undefined) | undefined;
45-
};
46-
47-
const getFallbackGatewayContextState = () =>
48-
resolveGlobalSingleton<FallbackGatewayContextState>(FALLBACK_GATEWAY_CONTEXT_STATE_KEY, () => ({
49-
context: undefined,
50-
resolveContext: undefined,
51-
}));
52-
53-
/** Set the process fallback gateway context for channel adapters outside WS requests. */
54-
export function setFallbackGatewayContext(ctx: GatewayRequestContext): () => void {
55-
const fallbackGatewayContextState = getFallbackGatewayContextState();
56-
fallbackGatewayContextState.context = ctx;
57-
fallbackGatewayContextState.resolveContext = undefined;
58-
return () => {
59-
const currentFallbackGatewayContextState = getFallbackGatewayContextState();
60-
if (
61-
currentFallbackGatewayContextState.context === ctx &&
62-
currentFallbackGatewayContextState.resolveContext === undefined
63-
) {
64-
currentFallbackGatewayContextState.context = undefined;
65-
}
66-
};
67-
}
68-
69-
export function setFallbackGatewayContextResolver(
70-
resolveContext: () => GatewayRequestContext | undefined,
71-
): () => void {
72-
const fallbackGatewayContextState = getFallbackGatewayContextState();
73-
fallbackGatewayContextState.context = undefined;
74-
fallbackGatewayContextState.resolveContext = resolveContext;
75-
return () => {
76-
const currentFallbackGatewayContextState = getFallbackGatewayContextState();
77-
if (currentFallbackGatewayContextState.resolveContext === resolveContext) {
78-
currentFallbackGatewayContextState.context = undefined;
79-
currentFallbackGatewayContextState.resolveContext = undefined;
80-
}
81-
};
82-
}
83-
84-
/** Clear the fallback gateway context installed for non-WS dispatch paths. */
85-
export function clearFallbackGatewayContext(): void {
86-
const fallbackGatewayContextState = getFallbackGatewayContextState();
87-
fallbackGatewayContextState.context = undefined;
88-
fallbackGatewayContextState.resolveContext = undefined;
89-
}
90-
91-
function getFallbackGatewayContext(): GatewayRequestContext | undefined {
92-
const fallbackGatewayContextState = getFallbackGatewayContextState();
93-
const resolved = fallbackGatewayContextState.resolveContext?.();
94-
return resolved ?? fallbackGatewayContextState.context;
95-
}
32+
import type { GatewayRequestHandler, GatewayRequestOptions } from "./server-methods/types.js";
33+
import { getFallbackGatewayContext } from "./server-plugin-fallback-context.js";
34+
35+
export {
36+
clearFallbackGatewayContext,
37+
setFallbackGatewayContext,
38+
setFallbackGatewayContextResolver,
39+
} from "./server-plugin-fallback-context.js";
9640

9741
export function hasInProcessGatewayContext(): boolean {
9842
return Boolean(getPluginRuntimeGatewayRequestScope()?.context ?? getFallbackGatewayContext());

0 commit comments

Comments
 (0)