Skip to content

Commit c5f76c3

Browse files
committed
fix(execution): re-queue work selected onto a retiring worker; stop E2E hosts with their workers
- dispatchToWorker re-queues when the selected worker retired during a target switch (not only when it was removed), and cleans it up if idle. - E2E hosts run in their own process group so cleanup also stops their worker children. - Sandbox rule notes the URL needs its token.
1 parent 71b922c commit c5f76c3

4 files changed

Lines changed: 20 additions & 9 deletions

File tree

‎.claude/rules/sim-sandbox.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ payload or `ivm.Reference` wrapper in the worker:
8888
## Where the worker runs
8989

9090
The pool in `isolated-vm.ts` opens each worker either as a local child process
91-
or, when `IVM_REMOTE_WORKER_URL` is set (and the `isolated-vm-local-workers`
92-
kill switch is off), as a WebSocket connection to `isolated-vm-host.cjs`, which runs the
91+
or, when `IVM_REMOTE_WORKER_URL` is set (with `IVM_REMOTE_WORKER_TOKEN`; a URL
92+
without a valid token fails executions rather than falling back) and the
93+
`isolated-vm-local-workers` kill switch is off, as a WebSocket connection to
94+
`isolated-vm-host.cjs`, which runs the
9395
same worker in a dedicated service that holds no platform credentials. Every
9496
rule in this file applies in both modes.
9597

‎.cursor/rules/sim-sandbox.mdc‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ payload or `ivm.Reference` wrapper in the worker:
8484
## Where the worker runs
8585

8686
The pool in `isolated-vm.ts` opens each worker either as a local child process
87-
or, when `IVM_REMOTE_WORKER_URL` is set (and the `isolated-vm-local-workers`
88-
kill switch is off), as a WebSocket connection to `isolated-vm-host.cjs`, which runs the
87+
or, when `IVM_REMOTE_WORKER_URL` is set (with `IVM_REMOTE_WORKER_TOKEN`; a URL
88+
without a valid token fails executions rather than falling back) and the
89+
`isolated-vm-local-workers` kill switch is off, as a WebSocket connection to
90+
`isolated-vm-host.cjs`, which runs the
8991
same worker in a dedicated service that holds no platform credentials. Every
9092
rule in this file applies in both modes.
9193

‎apps/sim/lib/execution/isolated-vm.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,8 +1155,7 @@ function spawnWorker(): Promise<WorkerInfo> {
11551155
return
11561156
}
11571157
workerInfo.ready = true
1158-
// The target changed while this worker was starting: it serves at most the
1159-
// execution awaiting it, then retires.
1158+
// The target changed while this worker was starting, so it takes no work.
11601159
workerInfo.retiring = workerInfo.targetKey !== workerTargetKey(workerTarget)
11611160
clearTimeout(startTimeout)
11621161
proc.off('message', readyHandler)
@@ -1265,8 +1264,10 @@ function dispatchToWorker(
12651264
return
12661265
}
12671266

1268-
// A target change can retire and remove the worker between its selection and this dispatch.
1269-
if (workers.get(workerInfo.id) !== workerInfo) {
1267+
// A target change can retire (or retire and remove) the worker between its selection and this
1268+
// dispatch; the execution then waits for a worker on the current target.
1269+
if (workers.get(workerInfo.id) !== workerInfo || workerInfo.retiring) {
1270+
if (workerInfo.retiring && workerInfo.activeExecutions === 0) cleanupWorker(workerInfo.id)
12701271
enqueueExecution(ownerState, req, resolve, state, brokers)
12711272
return
12721273
}

‎apps/sim/scripts/test-isolated-vm-remote-e2e.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ async function startHost(maxWorkers: number): Promise<Host> {
9090
SIM_HOST_ONLY_SETTING: HOST_ONLY_VALUE,
9191
},
9292
stdio: ['ignore', 'pipe', 'pipe'],
93+
// Its own process group, so cleanup can stop the host and its worker children together.
94+
detached: true,
9395
})
9496
const relay = (data: Buffer) => logger.info(`host:${port} ${data.toString().trim()}`)
9597
child.stdout?.on('data', relay)
@@ -410,7 +412,11 @@ run()
410412
process.exitCode = 1
411413
})
412414
.finally(async () => {
413-
for (const host of hosts) if (host.process.exitCode === null) host.process.kill('SIGKILL')
415+
for (const host of hosts) {
416+
try {
417+
if (host.process.pid) process.kill(-host.process.pid, 'SIGKILL')
418+
} catch {}
419+
}
414420
const report = {
415421
suite: 'isolated-vm-remote',
416422
startedAt,

0 commit comments

Comments
 (0)