补齐 Windows SpacetimeDB smoke 清理
Project CI / Frontend tests (pull_request) Successful in 3m59s
Project CI / Repository checks (pull_request) Successful in 5m35s
Project CI / Backend tests (pull_request) Successful in 7m44s
Project CI / Native shell tests (pull_request) Failing after 11m29s

修复管理员 procedure smoke 在 Windows 下只终止 wrapper 父进程的问题。
让编辑器幂等性 smoke 递归终止 spacetime 子进程树并正常退出。
保留非 Windows 的 SIGTERM/SIGKILL 清理路径。
补跑真实运行态 smoke、单测、ESLint、编码和 diff 检查。
This commit is contained in:
2026-08-27 13:17:48 +08:00
parent c0d590a187
commit b16dd70deb
2 changed files with 70 additions and 0 deletions
@@ -144,6 +144,10 @@ async function stopStandalone(child) {
if (child.exitCode !== null) {
return;
}
if (process.platform === 'win32') {
await stopWindowsProcessTree(child);
return;
}
child.kill('SIGTERM');
const exited = await Promise.race([
once(child, 'exit').then(() => true),
@@ -155,6 +159,37 @@ async function stopStandalone(child) {
}
}
async function stopWindowsProcessTree(child) {
if (typeof child.pid === 'number') {
await runTaskKill(child.pid);
}
const exited = await Promise.race([
once(child, 'exit').then(() => true),
delay(5_000).then(() => false),
]);
if (!exited && child.exitCode === null) {
child.kill('SIGKILL');
await once(child, 'exit');
}
}
function runTaskKill(pid) {
return new Promise((resolve, reject) => {
const taskKill = spawn('taskkill', ['/PID', String(pid), '/T', '/F'], {
stdio: 'ignore',
shell: false,
});
taskKill.once('error', reject);
taskKill.once('exit', (code, signal) => {
if (code === 0 || code === 128 || code === 1) {
resolve();
return;
}
reject(new Error(`taskkill exited with ${signal ?? code}`));
});
});
}
async function callProcedure(serverUrl, token, procedureName, input) {
const response = await fetch(
`${serverUrl}/v1/database/${database}/call/${procedureName}`,
@@ -228,6 +228,10 @@ export async function stopStandalone(child) {
if (child.exitCode !== null) {
return;
}
if (process.platform === 'win32') {
await stopWindowsProcessTree(child);
return;
}
child.kill('SIGTERM');
const exited = await Promise.race([
once(child, 'exit').then(() => true),
@@ -239,6 +243,37 @@ export async function stopStandalone(child) {
}
}
async function stopWindowsProcessTree(child) {
if (typeof child.pid === 'number') {
await runTaskKill(child.pid);
}
const exited = await Promise.race([
once(child, 'exit').then(() => true),
delay(5_000).then(() => false),
]);
if (!exited && child.exitCode === null) {
child.kill('SIGKILL');
await once(child, 'exit');
}
}
function runTaskKill(pid) {
return new Promise((resolve, reject) => {
const taskKill = spawn('taskkill', ['/PID', String(pid), '/T', '/F'], {
stdio: 'ignore',
shell: false,
});
taskKill.once('error', reject);
taskKill.once('exit', (code, signal) => {
if (code === 0 || code === 128 || code === 1) {
resolve();
return;
}
reject(new Error(`taskkill exited with ${signal ?? code}`));
});
});
}
function cliPrefix(configPath) {
return ['--config-path', configPath];
}