fix(cutover): close identity binding races

This commit is contained in:
chick
2026-07-18 18:13:53 +08:00
parent 63d167d720
commit d323370a75
+10 -10
View File
@@ -14,7 +14,7 @@ import {
} from 'node:fs/promises'; } from 'node:fs/promises';
import { createHash } from 'node:crypto'; import { createHash } from 'node:crypto';
import { request } from 'node:http'; import { request } from 'node:http';
import { basename, isAbsolute, join, resolve } from 'node:path'; import { isAbsolute, join, resolve } from 'node:path';
import { GATEWAY_AUTH_HEADER } from './runtime-config.js'; import { GATEWAY_AUTH_HEADER } from './runtime-config.js';
import { PRODUCTION_CUTOVER_ACK } from './canary-runtime.js'; import { PRODUCTION_CUTOVER_ACK } from './canary-runtime.js';
@@ -197,12 +197,7 @@ function exactKeys(
} }
function commandMatchesArgv(command: string, commandArgv: readonly string[]): boolean { function commandMatchesArgv(command: string, commandArgv: readonly string[]): boolean {
const rendered = commandArgv.join(' '); return commandArgv.join(' ') === command;
if (rendered === command) return true;
const executable = commandArgv[0];
if (executable === undefined) return false;
const args = commandArgv.slice(1);
return [basename(executable), ...args].join(' ') === command;
} }
function safeString(value: unknown, label: string): string { function safeString(value: unknown, label: string): string {
@@ -431,12 +426,12 @@ export async function cutover(
MULTI_SIMADMIN_CUTOVER_ACK: PRODUCTION_CUTOVER_ACK, MULTI_SIMADMIN_CUTOVER_ACK: PRODUCTION_CUTOVER_ACK,
MULTI_SIMADMIN_GATEWAY_TOKEN: gatewayToken, MULTI_SIMADMIN_GATEWAY_TOKEN: gatewayToken,
}); });
gatewayCommand = await system.command(gatewayPid);
gatewayIdentity = await system.identity(gatewayPid);
if (!(await waitForGateway(system, gatewayPid, gatewayToken))) if (!(await waitForGateway(system, gatewayPid, gatewayToken)))
throw new Error( throw new Error(
'Production gateway failed authenticated ownership verification on port 8788', 'Production gateway failed authenticated ownership verification on port 8788',
); );
gatewayCommand = await system.command(gatewayPid);
gatewayIdentity = await system.identity(gatewayPid);
await durableState(plan, { await durableState(plan, {
...preparedState(plan), ...preparedState(plan),
phase: 'active', phase: 'active',
@@ -450,7 +445,12 @@ export async function cutover(
try { try {
const actual = await system.command(gatewayPid); const actual = await system.command(gatewayPid);
const identity = await system.identity(gatewayPid); const identity = await system.identity(gatewayPid);
if (actual === gatewayCommand && identity === gatewayIdentity) { if (
(gatewayCommand === undefined || actual === gatewayCommand) &&
(gatewayIdentity === undefined || identity === gatewayIdentity) &&
actual !== '' &&
identity !== ''
) {
system.signal(gatewayPid, 'SIGTERM'); system.signal(gatewayPid, 'SIGTERM');
await system.waitGone(gatewayPid); await system.waitGone(gatewayPid);
} }