Skip to content

Commit 9bac300

Browse files
committed
🤖 refactor: simplify ssh runtime scaling flow
1 parent 95467e3 commit 9bac300

14 files changed

Lines changed: 250 additions & 607 deletions

src/node/runtime/RemoteRuntime.test.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ class TestRemoteRuntime extends RemoteRuntime {
3333
constructor(
3434
private readonly childProcess: FakeChildProcess,
3535
private readonly onExitCalls: Array<[number, string]>,
36-
private readonly onCloseCalls: number[],
37-
private readonly onExitCodeCalls: number[]
36+
private readonly onCloseCalls: number[]
3837
) {
3938
super();
4039
}
@@ -66,10 +65,6 @@ class TestRemoteRuntime extends RemoteRuntime {
6665
return `cd ${cwd}`;
6766
}
6867

69-
protected override onExitCode(exitCode: number): void {
70-
this.onExitCodeCalls.push(exitCode);
71-
}
72-
7368
resolvePath(targetPath: string): Promise<string> {
7469
return Promise.resolve(targetPath);
7570
}
@@ -108,8 +103,7 @@ describe("RemoteRuntime synthetic exit handling", () => {
108103
const childProcess = new FakeChildProcess();
109104
const onExitCalls: Array<[number, string]> = [];
110105
const onCloseCalls: number[] = [];
111-
const onExitCodeCalls: number[] = [];
112-
const runtime = new TestRemoteRuntime(childProcess, onExitCalls, onCloseCalls, onExitCodeCalls);
106+
const runtime = new TestRemoteRuntime(childProcess, onExitCalls, onCloseCalls);
113107
const controller = new AbortController();
114108

115109
const stream = await runtime.exec("echo ok", { cwd: "/tmp", abortSignal: controller.signal });
@@ -119,15 +113,13 @@ describe("RemoteRuntime synthetic exit handling", () => {
119113
expect(await stream.exitCode).toBe(EXIT_CODE_ABORTED);
120114
expect(onExitCalls).toEqual([]);
121115
expect(onCloseCalls).toEqual([1]);
122-
expect(onExitCodeCalls).toEqual([EXIT_CODE_ABORTED]);
123116
});
124117

125118
test("does not forward timed-out exits to transport onExit hooks", async () => {
126119
const childProcess = new FakeChildProcess();
127120
const onExitCalls: Array<[number, string]> = [];
128121
const onCloseCalls: number[] = [];
129-
const onExitCodeCalls: number[] = [];
130-
const runtime = new TestRemoteRuntime(childProcess, onExitCalls, onCloseCalls, onExitCodeCalls);
122+
const runtime = new TestRemoteRuntime(childProcess, onExitCalls, onCloseCalls);
131123

132124
const stream = await runtime.exec("echo ok", { cwd: "/tmp", timeout: 0.01 });
133125
await new Promise((resolve) => setTimeout(resolve, 20));
@@ -136,6 +128,5 @@ describe("RemoteRuntime synthetic exit handling", () => {
136128
expect(await stream.exitCode).toBe(EXIT_CODE_TIMEOUT);
137129
expect(onExitCalls).toEqual([]);
138130
expect(onCloseCalls).toEqual([1]);
139-
expect(onExitCodeCalls).toEqual([EXIT_CODE_TIMEOUT]);
140131
});
141132
});

src/node/runtime/RemoteRuntime.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
* - spawnRemoteProcess() - how to spawn the external process (ssh/docker)
1212
* - getBasePath() - base directory for workspace operations
1313
* - quoteForRemote() - path quoting strategy
14-
* - onExitCode() - optional exit code handling (SSH connection pool)
1514
*/
1615

1716
import type { ChildProcess } from "child_process";
@@ -45,8 +44,6 @@ import { getAtomicWriteTempPath } from "./atomicWriteTempPath";
4544
export interface SpawnResult {
4645
/** The spawned child process */
4746
process: ChildProcess;
48-
/** Optional async work to do before exec (e.g., acquire connection) */
49-
preExec?: Promise<void>;
5047
/** Optional transport-scoped exit handling (e.g., master-pool health accounting). */
5148
onExit?: (exitCode: number, stderr: string) => void;
5249
/** Optional close handling that must run even for synthetic abort/timeout exits. */
@@ -65,7 +62,7 @@ export abstract class RemoteRuntime implements Runtime {
6562
*
6663
* @param fullCommand The full shell command to execute (already wrapped in bash -c)
6764
* @param options Original exec options
68-
* @returns The spawned process and optional pre-exec work
65+
* @returns The spawned process and optional transport lifecycle hooks
6966
*/
7067
protected abstract spawnRemoteProcess(
7168
fullCommand: string,
@@ -90,15 +87,6 @@ export abstract class RemoteRuntime implements Runtime {
9087
*/
9188
protected abstract cdCommand(cwd: string): string;
9289

93-
/**
94-
* Called when exec completes with an exit code.
95-
* Subclasses can use this for connection pool health tracking.
96-
* @param stderr - Captured stderr for error reporting (e.g., SSH connection failures)
97-
*/
98-
protected onExitCode(_exitCode: number, _options: ExecOptions, _stderr: string): void {
99-
// Default: no-op. SSH overrides to report to connection pool.
100-
}
101-
10290
/**
10391
* Command prefix (e.g., "SSH" or "Docker") for logging.
10492
*/
@@ -185,8 +173,6 @@ export abstract class RemoteRuntime implements Runtime {
185173
spawnResult.onExit?.(finalExitCode, stderrForErrorReporting);
186174
}
187175
spawnResult.onClose?.();
188-
// Let subclass handle exit code (e.g., SSH connection pool)
189-
this.onExitCode(finalExitCode, options, stderrForErrorReporting);
190176

191177
resolve(finalExitCode);
192178
});

0 commit comments

Comments
 (0)