diff --git a/src/daemon/launchd-plist.ts b/src/daemon/launchd-plist.ts index b292ff45974..37448cdcebf 100644 --- a/src/daemon/launchd-plist.ts +++ b/src/daemon/launchd-plist.ts @@ -1,5 +1,10 @@ import fs from "node:fs/promises"; +// launchd applies ThrottleInterval to any rapid relaunch, including +// intentional gateway restarts. Keep it low so CLI restarts and forced +// reinstalls do not stall for a full minute. +export const LAUNCH_AGENT_THROTTLE_INTERVAL_SECONDS = 1; + const plistEscape = (value: string): string => value .replaceAll("&", "&") @@ -106,5 +111,5 @@ export function buildLaunchAgentPlist({ ? `\n Comment\n ${plistEscape(comment.trim())}` : ""; const envXml = renderEnvDict(environment); - return `\n\n\n \n Label\n ${plistEscape(label)}\n ${commentXml}\n RunAtLoad\n \n KeepAlive\n \n ThrottleInterval\n 60\n ProgramArguments\n ${argsXml}\n \n ${workingDirXml}\n StandardOutPath\n ${plistEscape(stdoutPath)}\n StandardErrorPath\n ${plistEscape(stderrPath)}${envXml}\n \n\n`; + return `\n\n\n \n Label\n ${plistEscape(label)}\n ${commentXml}\n RunAtLoad\n \n KeepAlive\n \n ThrottleInterval\n ${LAUNCH_AGENT_THROTTLE_INTERVAL_SECONDS}\n ProgramArguments\n ${argsXml}\n \n ${workingDirXml}\n StandardOutPath\n ${plistEscape(stdoutPath)}\n StandardErrorPath\n ${plistEscape(stderrPath)}${envXml}\n \n\n`; } diff --git a/src/daemon/launchd.test.ts b/src/daemon/launchd.test.ts index 85c7a3350e9..6cf31dc5ce5 100644 --- a/src/daemon/launchd.test.ts +++ b/src/daemon/launchd.test.ts @@ -1,5 +1,6 @@ import { PassThrough } from "node:stream"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import { LAUNCH_AGENT_THROTTLE_INTERVAL_SECONDS } from "./launchd-plist.js"; import { installLaunchAgent, isLaunchAgentListed, @@ -199,7 +200,7 @@ describe("launchd install", () => { expect(plist).toContain(""); expect(plist).not.toContain("SuccessfulExit"); expect(plist).toContain("ThrottleInterval"); - expect(plist).toContain("60"); + expect(plist).toContain(`${LAUNCH_AGENT_THROTTLE_INTERVAL_SECONDS}`); }); it("restarts LaunchAgent with bootout-bootstrap-kickstart order", async () => {