Fix release-blocking CI failures
This commit is contained in:
@@ -359,8 +359,9 @@ describe("daemon-manager commands", () => {
|
|||||||
|
|
||||||
expect(thrown).toBeInstanceOf(Error);
|
expect(thrown).toBeInstanceOf(Error);
|
||||||
const message = thrown?.message ?? "";
|
const message = thrown?.message ?? "";
|
||||||
|
const recentLogsLabel = message.match(/Recent logs \(([^)]*)\):/)?.[1];
|
||||||
expect(message).toContain("Daemon failed to start: exit code 1");
|
expect(message).toContain("Daemon failed to start: exit code 1");
|
||||||
expect(message).toContain(`Recent logs (${mocks.paseoHome}/daemon.log):`);
|
expect(recentLogsLabel?.split(/[\\/]/).at(-1)).toBe("daemon.log");
|
||||||
expect(message).toContain("recent daemon failure");
|
expect(message).toContain("recent daemon failure");
|
||||||
expect(mocks.spawnProcess).toHaveBeenCalledWith(
|
expect(mocks.spawnProcess).toHaveBeenCalledWith(
|
||||||
"node",
|
"node",
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
import type { Event as OpenCodeEvent, OpencodeClient } from "@opencode-ai/sdk/v2/client";
|
import type { OpencodeClient } from "@opencode-ai/sdk/v2/client";
|
||||||
|
|
||||||
import type { OpenCodeRuntime, OpenCodeServerAcquisition } from "../runtime.js";
|
import type { OpenCodeRuntime, OpenCodeServerAcquisition } from "../runtime.js";
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ export class TestOpenCodeClient {
|
|||||||
sessionMessagesResponse: OpenCodeResponse = { data: [] };
|
sessionMessagesResponse: OpenCodeResponse = { data: [] };
|
||||||
sessionPromptAsyncEvents: unknown[] = [idleEvent()];
|
sessionPromptAsyncEvents: unknown[] = [idleEvent()];
|
||||||
sessionPromptAsyncResponse: OpenCodeResponse = {};
|
sessionPromptAsyncResponse: OpenCodeResponse = {};
|
||||||
sessionSummarizeEvents: OpenCodeEvent[] = [];
|
sessionSummarizeEvents: unknown[] = [idleEvent()];
|
||||||
sessionSummarizeResponse: OpenCodeResponse = { data: {} };
|
sessionSummarizeResponse: OpenCodeResponse = { data: {} };
|
||||||
sessionUpdateResponse: OpenCodeResponse = {};
|
sessionUpdateResponse: OpenCodeResponse = {};
|
||||||
private readonly queuedEventStream = createQueuedEventStream();
|
private readonly queuedEventStream = createQueuedEventStream();
|
||||||
|
|||||||
@@ -173,13 +173,17 @@ async function main() {
|
|||||||
|
|
||||||
const supervisorPid = process.ppid;
|
const supervisorPid = process.ppid;
|
||||||
let lastSupervisorHeartbeatAt = Date.now();
|
let lastSupervisorHeartbeatAt = Date.now();
|
||||||
let supervisorShutdownRequested = false;
|
let supervisorExitRequested = false;
|
||||||
const requestSupervisorShutdown = (reason: string) => {
|
const exitAfterSupervisorLoss = () => {
|
||||||
if (supervisorShutdownRequested) {
|
if (supervisorExitRequested) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
supervisorShutdownRequested = true;
|
supervisorExitRequested = true;
|
||||||
beginShutdown(reason);
|
|
||||||
|
// The supervisor owns the worker's stdout/stderr pipes. Once it is gone,
|
||||||
|
// logging during graceful shutdown can block on the broken pipe and leave
|
||||||
|
// the daemon orphaned, so supervisor loss is a hard process boundary.
|
||||||
|
process.exit(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
process.on("message", (message: unknown) => {
|
process.on("message", (message: unknown) => {
|
||||||
@@ -192,13 +196,19 @@ async function main() {
|
|||||||
lastSupervisorHeartbeatAt = Date.now();
|
lastSupervisorHeartbeatAt = Date.now();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
process.on("disconnect", () => requestSupervisorShutdown("supervisor disconnect"));
|
process.on("disconnect", exitAfterSupervisorLoss);
|
||||||
|
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
const ipcConnected = typeof process.connected === "boolean" ? process.connected : true;
|
const ipcConnected = typeof process.connected === "boolean" ? process.connected : true;
|
||||||
const heartbeatExpired = Date.now() - lastSupervisorHeartbeatAt > 3500;
|
const heartbeatExpired = Date.now() - lastSupervisorHeartbeatAt > 3500;
|
||||||
if (ipcConnected === false || !isPidAlive(supervisorPid) || heartbeatExpired) {
|
const supervisorChanged = process.ppid !== supervisorPid;
|
||||||
requestSupervisorShutdown("supervisor disconnect");
|
if (
|
||||||
|
ipcConnected === false ||
|
||||||
|
supervisorChanged ||
|
||||||
|
!isPidAlive(supervisorPid) ||
|
||||||
|
heartbeatExpired
|
||||||
|
) {
|
||||||
|
exitAfterSupervisorLoss();
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
timer.unref();
|
timer.unref();
|
||||||
|
|||||||
Reference in New Issue
Block a user