Revert "fix(gateway): refine process termination and wait logic on retry" (#754)
This commit is contained in:
@@ -297,13 +297,11 @@ export class GatewayManager extends EventEmitter {
|
|||||||
process.kill(pid, 0);
|
process.kill(pid, 0);
|
||||||
// Still alive — keep this.process so later cleanup can reach it
|
// Still alive — keep this.process so later cleanup can reach it
|
||||||
} catch {
|
} catch {
|
||||||
// Process is gone — safe to clear the handle and ownership flag
|
// Process is gone — safe to clear the handle
|
||||||
this.process = null;
|
this.process = null;
|
||||||
this.ownsProcess = false;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.process = null;
|
this.process = null;
|
||||||
this.ownsProcess = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -98,15 +98,14 @@ export async function runGatewayStartupSequence(hooks: StartupHooks): Promise<vo
|
|||||||
|
|
||||||
if (recoveryAction === 'retry') {
|
if (recoveryAction === 'retry') {
|
||||||
logger.warn(`Transient start error: ${String(error)}. Retrying... (${startAttempts}/${maxStartAttempts})`);
|
logger.warn(`Transient start error: ${String(error)}. Retrying... (${startAttempts}/${maxStartAttempts})`);
|
||||||
// Terminate the previously spawned process before the backoff delay so
|
await hooks.delay(1000);
|
||||||
// it releases the port as early as possible; the subsequent delay gives
|
// Terminate the previously spawned process before retrying so it doesn't
|
||||||
// the OS time to recycle the port (especially TCP TIME_WAIT on Windows).
|
// hold the port and cause another handshake failure.
|
||||||
if (hooks.terminateOwnedProcess) {
|
if (hooks.terminateOwnedProcess) {
|
||||||
await hooks.terminateOwnedProcess().catch((err) => {
|
await hooks.terminateOwnedProcess().catch((err) => {
|
||||||
logger.warn('Failed to terminate owned process before retry:', err);
|
logger.warn('Failed to terminate owned process before retry:', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await hooks.delay(1000);
|
|
||||||
hooks.assertLifecycle('start/retry-pre-port-wait');
|
hooks.assertLifecycle('start/retry-pre-port-wait');
|
||||||
// Wait for port to become free before retrying (handles lingering processes).
|
// Wait for port to become free before retrying (handles lingering processes).
|
||||||
// Use a short-polling AbortController so that a superseding stop()/restart()
|
// Use a short-polling AbortController so that a superseding stop()/restart()
|
||||||
@@ -123,12 +122,6 @@ export async function runGatewayStartupSequence(hooks: StartupHooks): Promise<vo
|
|||||||
}, 500);
|
}, 500);
|
||||||
try {
|
try {
|
||||||
await hooks.waitForPortFree(hooks.port, abortController.signal);
|
await hooks.waitForPortFree(hooks.port, abortController.signal);
|
||||||
} catch (portWaitError) {
|
|
||||||
// If the wait was aborted due to lifecycle supersede, convert to
|
|
||||||
// LifecycleSupersededError so the outer handler propagates correctly.
|
|
||||||
hooks.assertLifecycle('start/retry-port-wait-aborted');
|
|
||||||
// If assertLifecycle didn't throw, it's a genuine port-wait error — rethrow.
|
|
||||||
throw portWaitError;
|
|
||||||
} finally {
|
} finally {
|
||||||
clearInterval(lifecyclePollInterval);
|
clearInterval(lifecyclePollInterval);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ export async function waitForPortFree(port: number, timeoutMs = 30000, signal?:
|
|||||||
while (Date.now() - start < timeoutMs) {
|
while (Date.now() - start < timeoutMs) {
|
||||||
if (signal?.aborted) {
|
if (signal?.aborted) {
|
||||||
logger.debug(`waitForPortFree: aborted while waiting for port ${port}`);
|
logger.debug(`waitForPortFree: aborted while waiting for port ${port}`);
|
||||||
throw new Error(`waitForPortFree: aborted while waiting for port ${port}`);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const available = await new Promise<boolean>((resolve) => {
|
const available = await new Promise<boolean>((resolve) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user