Merge pull request #20298 from backstage/rugvip/windev

backend-next: fixes for development on Windows
This commit is contained in:
Patrik Oldsberg
2023-10-02 11:02:40 +02:00
committed by GitHub
6 changed files with 56 additions and 30 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-dev-utils': patch
---
Fix an issue where early IPC responses would be lost.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows.
+31 -29
View File
@@ -38,6 +38,8 @@ type Response =
const requestType = '@backstage/cli/channel/request';
const responseType = '@backstage/cli/channel/response';
const IPC_TIMEOUT_MS = 5000;
/**
* The client side of an IPC communication channel.
*
@@ -78,43 +80,43 @@ export class BackstageIpcClient {
body,
};
this.#sendMessage(request, (e: Error) => {
if (e) {
reject(e);
let timeout: NodeJS.Timeout | undefined = undefined;
const messageHandler = (response: Response) => {
if (response?.type !== responseType) {
return;
}
if (response.id !== id) {
return;
}
let timeout: NodeJS.Timeout | undefined = undefined;
clearTimeout(timeout);
timeout = undefined;
process.removeListener('message', messageHandler);
const messageHandler = (response: Response) => {
if (response?.type !== responseType) {
return;
}
if (response.id !== id) {
return;
if ('error' in response) {
const error = new Error(response.error.message);
if (response.error.name) {
error.name = response.error.name;
}
reject(error);
} else {
resolve(response.body as TResponseBody);
}
};
if ('error' in response) {
const error = new Error(response.error.message);
if (response.error.name) {
error.name = response.error.name;
}
reject(error);
} else {
resolve(response.body as TResponseBody);
}
timeout = setTimeout(() => {
reject(new Error(`IPC request '${method}' with ID ${id} timed out`));
process.removeListener('message', messageHandler);
}, IPC_TIMEOUT_MS);
timeout.unref();
clearTimeout(timeout);
process.removeListener('message', messageHandler);
};
process.addListener('message', messageHandler as () => void);
timeout = setTimeout(() => {
reject(new Error(`IPC request '${method}' with ID ${id} timed out`));
process.removeListener('message', messageHandler);
}, 5000);
timeout.unref();
process.addListener('message', messageHandler as () => void);
this.#sendMessage(request, (e: Error) => {
if (e) {
reject(e);
}
});
});
}
+1
View File
@@ -78,6 +78,7 @@
"cross-fetch": "^3.1.5",
"cross-spawn": "^7.0.3",
"css-loader": "^6.5.1",
"ctrlc-windows": "^2.1.0",
"diff": "^5.0.0",
"esbuild": "^0.19.0",
"esbuild-loader": "^2.18.0",
@@ -18,6 +18,7 @@ import { FSWatcher, watch } from 'chokidar';
import { BackendServeOptions } from '../bundler/types';
import type { ChildProcess } from 'child_process';
import { ctrlc } from 'ctrlc-windows';
import { IpcServer } from './IpcServer';
import { ServerDataStore } from './ServerDataStore';
import debounce from 'lodash/debounce';
@@ -57,7 +58,11 @@ export async function startBackendExperimental(options: BackendServeOptions) {
if (child && !child.killed && child.exitCode === null) {
// We always wait for the existing process to exit, to make sure we don't get IPC conflicts
shutdownPromise = new Promise(resolve => child!.once('exit', resolve));
child.kill();
if (process.platform === 'win32' && child.pid) {
ctrlc(child.pid);
} else {
child.kill();
}
await shutdownPromise;
shutdownPromise = undefined;
}
+8
View File
@@ -3795,6 +3795,7 @@ __metadata:
cross-fetch: ^3.1.5
cross-spawn: ^7.0.3
css-loader: ^6.5.1
ctrlc-windows: ^2.1.0
del: ^7.0.0
diff: ^5.0.0
esbuild: ^0.19.0
@@ -23050,6 +23051,13 @@ __metadata:
languageName: node
linkType: hard
"ctrlc-windows@npm:^2.1.0":
version: 2.1.0
resolution: "ctrlc-windows@npm:2.1.0"
checksum: 0f0582ba9516290d3e90ea7b91710f8b9b110e1ed29b7c84ebd44c16368b2553722b86a17226120ca3ea0ef679ac3596f48104cc113cfb7c3d07260f6c92e38b
languageName: node
linkType: hard
"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6":
version: 3.2.3
resolution: "d3-array@npm:3.2.3"