( workerInfo: WorkerInfo, ownerState: OwnerState, req: IsolatedVMExecutionRequest, resolve: (result: IsolatedVMExecutionResult) => void, state: ExecutionState, brokers?: Record<string, IsolatedVMBrokerHandler> )
| 1076 | } |
| 1077 | |
| 1078 | function dispatchToWorker( |
| 1079 | workerInfo: WorkerInfo, |
| 1080 | ownerState: OwnerState, |
| 1081 | req: IsolatedVMExecutionRequest, |
| 1082 | resolve: (result: IsolatedVMExecutionResult) => void, |
| 1083 | state: ExecutionState, |
| 1084 | brokers?: Record<string, IsolatedVMBrokerHandler> |
| 1085 | ) { |
| 1086 | // Caller may have aborted between acquireWorker() and dispatch. Skip the |
| 1087 | // round-trip entirely and let the abort listener handle settlement. |
| 1088 | if (state.cancelled) { |
| 1089 | resolve({ |
| 1090 | result: null, |
| 1091 | stdout: '', |
| 1092 | error: { message: 'Execution cancelled', name: 'AbortError' }, |
| 1093 | }) |
| 1094 | drainQueue() |
| 1095 | return |
| 1096 | } |
| 1097 | |
| 1098 | const execId = ++executionIdCounter |
| 1099 | state.workerId = workerInfo.id |
| 1100 | state.execId = execId |
| 1101 | |
| 1102 | if (workerInfo.idleTimeout) { |
| 1103 | clearTimeout(workerInfo.idleTimeout) |
| 1104 | workerInfo.idleTimeout = null |
| 1105 | } |
| 1106 | |
| 1107 | const timeout = setTimeout(() => { |
| 1108 | workerInfo.pendingExecutions.delete(execId) |
| 1109 | workerInfo.activeExecutions-- |
| 1110 | totalActiveExecutions-- |
| 1111 | ownerState.activeExecutions = Math.max(0, ownerState.activeExecutions - 1) |
| 1112 | maybeCleanupOwner(ownerState.ownerKey) |
| 1113 | workerInfo.lifetimeExecutions++ |
| 1114 | if (workerInfo.lifetimeExecutions >= MAX_EXECUTIONS_PER_WORKER && !workerInfo.retiring) { |
| 1115 | workerInfo.retiring = true |
| 1116 | logger.info('Worker marked for retirement', { |
| 1117 | workerId: workerInfo.id, |
| 1118 | lifetimeExecutions: workerInfo.lifetimeExecutions, |
| 1119 | }) |
| 1120 | } |
| 1121 | resolve({ |
| 1122 | result: null, |
| 1123 | stdout: '', |
| 1124 | error: { message: `Execution timed out after ${req.timeoutMs}ms`, name: 'TimeoutError' }, |
| 1125 | }) |
| 1126 | if (workerInfo.retiring && workerInfo.activeExecutions === 0) { |
| 1127 | cleanupWorker(workerInfo.id) |
| 1128 | } else { |
| 1129 | resetWorkerIdleTimeout(workerInfo.id) |
| 1130 | } |
| 1131 | drainQueue() |
| 1132 | }, req.timeoutMs + 1000) |
| 1133 | |
| 1134 | workerInfo.pendingExecutions.set(execId, { |
| 1135 | resolve, |
no test coverage detected