mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:10:45 +00:00
fix: wait for qa gateway restart boundary
This commit is contained in:
@@ -328,6 +328,32 @@ describe("buildQaRuntimeEnv", () => {
|
||||
expect(__testing.isRetryableGatewayCallError("permission denied")).toBe(false);
|
||||
});
|
||||
|
||||
it("waits for a fresh in-process restart boundary after the current log offset", async () => {
|
||||
let logs = "old restart mode: in-process restart\n";
|
||||
const offset = logs.length;
|
||||
const wait = __testing.waitForQaGatewayRestartBoundary({
|
||||
logs: () => logs,
|
||||
offset,
|
||||
pollMs: 1,
|
||||
timeoutMs: 100,
|
||||
});
|
||||
|
||||
logs += "signal SIGUSR1 received\nrestart mode: in-process restart\n";
|
||||
|
||||
await expect(wait).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("times out when a SIGUSR1 restart never reaches the boundary", async () => {
|
||||
await expect(
|
||||
__testing.waitForQaGatewayRestartBoundary({
|
||||
logs: () => "signal SIGUSR1 received\n",
|
||||
offset: 0,
|
||||
pollMs: 1,
|
||||
timeoutMs: 1,
|
||||
}),
|
||||
).rejects.toThrow("qa gateway child did not reach restart boundary");
|
||||
});
|
||||
|
||||
it("stages a live Anthropic setup-token profile for isolated QA workers", async () => {
|
||||
const stateDir = await mkdtemp(path.join(os.tmpdir(), "qa-setup-token-state-"));
|
||||
cleanups.push(async () => {
|
||||
|
||||
@@ -268,6 +268,24 @@ async function fetchLocalGatewayHealth(params: {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForQaGatewayRestartBoundary(params: {
|
||||
logs: () => string;
|
||||
offset: number;
|
||||
pollMs?: number;
|
||||
timeoutMs?: number;
|
||||
}) {
|
||||
const timeoutMs = params.timeoutMs ?? 30_000;
|
||||
const pollMs = params.pollMs ?? 100;
|
||||
const startedAt = Date.now();
|
||||
while (Date.now() - startedAt < timeoutMs) {
|
||||
if (params.logs().slice(params.offset).includes("restart mode:")) {
|
||||
return;
|
||||
}
|
||||
await sleep(pollMs);
|
||||
}
|
||||
throw new Error(`qa gateway child did not reach restart boundary within ${timeoutMs}ms`);
|
||||
}
|
||||
|
||||
export const __testing = {
|
||||
assertQaArtifactDirWithinRepo,
|
||||
buildQaRuntimeEnv,
|
||||
@@ -283,6 +301,7 @@ export const __testing = {
|
||||
stageQaLiveAnthropicSetupToken,
|
||||
stageQaMockAuthProfiles,
|
||||
resolveQaLiveCliAuthEnv,
|
||||
waitForQaGatewayRestartBoundary,
|
||||
resolveQaOwnerPluginIdsForProviderIds,
|
||||
resolveQaBundledPluginSourceDir,
|
||||
resolveQaRuntimeHostVersion,
|
||||
@@ -816,7 +835,20 @@ export async function startQaGatewayChild(params: {
|
||||
if (!activeChild.pid) {
|
||||
throw new Error("qa gateway child has no pid");
|
||||
}
|
||||
const restartLogOffset = logs().length;
|
||||
process.kill(activeChild.pid, signal);
|
||||
if (signal === "SIGUSR1") {
|
||||
await waitForQaGatewayRestartBoundary({
|
||||
logs,
|
||||
offset: restartLogOffset,
|
||||
});
|
||||
await waitForGatewayReady({
|
||||
baseUrl,
|
||||
logs,
|
||||
child: activeChild,
|
||||
timeoutMs: 120_000,
|
||||
});
|
||||
}
|
||||
},
|
||||
async restartAfterStateMutation(
|
||||
mutateState: (context: QaGatewayChildStateMutationContext) => Promise<void>,
|
||||
|
||||
Reference in New Issue
Block a user