
























@@ -112,6 +112,8 @@ export async function runGatewayLoop(params: {
112112// The HTTP server can report ready before params.start returns its close handle.
113113// Defer lifecycle signals from that window until the loop can close and advance.
114114let pendingStartupRequest: GatewayRunSignalRequest | null = null;
115+let pendingStartupForceExitTimer: ReturnType<typeof setTimeout> | null = null;
116+let restartDrainingMarkPromise: Promise<void> | null = null;
115117let startupFailedWithoutServerHandle = false;
116118const processInstanceId = randomUUID();
117119const waitForHealthyChild = params.waitForHealthyChild ?? waitForHealthyGatewayChild;
@@ -305,6 +307,32 @@ export async function runGatewayLoop(params: {
305307306308const SUPERVISOR_STOP_TIMEOUT_MS = 30_000;
307309const SHUTDOWN_TIMEOUT_MS = SUPERVISOR_STOP_TIMEOUT_MS - 5_000;
310+const clearPendingStartupForceExitTimer = () => {
311+if (!pendingStartupForceExitTimer) {
312+return;
313+}
314+clearTimeout(pendingStartupForceExitTimer);
315+pendingStartupForceExitTimer = null;
316+};
317+const armPendingStartupForceExitTimer = () => {
318+if (pendingStartupForceExitTimer) {
319+return;
320+}
321+pendingStartupForceExitTimer = setTimeout(() => {
322+pendingStartupForceExitTimer = null;
323+gatewayLog.error(
324+"startup restart request timed out before gateway returned a close handle; exiting for supervisor recovery",
325+);
326+void (async () => {
327+try {
328+await writeStabilityBundle("gateway.restart_startup_request_timeout");
329+} finally {
330+exitProcess(1);
331+}
332+})();
333+}, SHUTDOWN_TIMEOUT_MS);
334+pendingStartupForceExitTimer.unref?.();
335+};
308336const resolveRestartDrainTimeoutMs = async (
309337restartIntent?: RestartIntentOptions,
310338): Promise<RestartDrainTimeoutMs> => {
@@ -323,6 +351,18 @@ export async function runGatewayLoop(params: {
323351return DEFAULT_RESTART_DRAIN_TIMEOUT_MS;
324352}
325353};
354+const markRestartDraining = async () => {
355+if (!restartDrainingMarkPromise) {
356+restartDrainingMarkPromise = (async () => {
357+const { markGatewayDraining } = await loadGatewayLifecycleRuntimeModule();
358+markGatewayDraining();
359+})().catch((err) => {
360+restartDrainingMarkPromise = null;
361+throw err;
362+});
363+}
364+await restartDrainingMarkPromise;
365+};
326366327367const runAcceptedRequest = ({
328368 action,
@@ -404,7 +444,6 @@ export async function runGatewayLoop(params: {
404444 getInspectableActiveTaskRestartBlockers,
405445 getActiveEmbeddedRunCount,
406446 getActiveTaskCount,
407- markGatewayDraining,
408447 waitForActiveEmbeddedRuns,
409448 waitForActiveTasks,
410449} = await loadGatewayLifecycleRuntimeModule();
@@ -439,7 +478,7 @@ export async function runGatewayLoop(params: {
439478440479// Reject new enqueues immediately during the drain window so
441480// sessions get an explicit restart error instead of silent task loss.
442-markGatewayDraining();
481+await markRestartDraining();
443482const activeTasks = getActiveTaskCount();
444483const activeRuns = getActiveEmbeddedRunCount();
445484activeTasksAtDrainStart = activeTasks;
@@ -540,6 +579,7 @@ export async function runGatewayLoop(params: {
540579}
541580const request = pendingStartupRequest;
542581pendingStartupRequest = null;
582+clearPendingStartupForceExitTimer();
543583startupFailedWithoutServerHandle = false;
544584runAcceptedRequest(request);
545585};
@@ -554,6 +594,7 @@ export async function runGatewayLoop(params: {
554594if (action === "stop" && pendingStartupRequest && !server) {
555595gatewayLog.info(`received ${signal}; overriding pending startup restart with shutdown`);
556596pendingStartupRequest = null;
597+clearPendingStartupForceExitTimer();
557598startupFailedWithoutServerHandle = false;
558599runAcceptedRequest(acceptedRequest);
559600return;
@@ -583,6 +624,10 @@ export async function runGatewayLoop(params: {
583624}
584625if (!server || !restartResolver) {
585626pendingStartupRequest = acceptedRequest;
627+void markRestartDraining().catch((err) => {
628+gatewayLog.warn(`failed to mark gateway draining for startup restart: ${String(err)}`);
629+});
630+armPendingStartupForceExitTimer();
586631return;
587632}
588633runAcceptedRequest(acceptedRequest);
@@ -668,6 +713,7 @@ export async function runGatewayLoop(params: {
668713let isFirstStart = true;
669714for (;;) {
670715await onIteration();
716+restartDrainingMarkPromise = null;
671717let startupFailedBeforeServerHandle = false;
672718try {
673719server = await params.start({ startupStartedAt });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。