@@ -22,6 +22,7 @@ import { randomBytes } from "node:crypto";
2222import { SnapshotManager , SnapshotState } from "./snapshot.js" ;
2323import type { SupervisorSocket } from "./controller.js" ;
2424import { RunNotifier } from "./notifier.js" ;
25+ import { TaskRunProcessProvider } from "./taskRunProcessProvider.js" ;
2526
2627class ExecutionAbortError extends Error {
2728 constructor ( message : string ) {
@@ -36,6 +37,7 @@ type RunExecutionOptions = {
3637 httpClient : WorkloadHttpClient ;
3738 logger : RunLogger ;
3839 supervisorSocket : SupervisorSocket ;
40+ taskRunProcessProvider : TaskRunProcessProvider ;
3941} ;
4042
4143type RunExecutionPrepareOptions = {
@@ -77,6 +79,7 @@ export class RunExecution {
7779 private supervisorSocket : SupervisorSocket ;
7880 private notifier ?: RunNotifier ;
7981 private metadataClient ?: MetadataClient ;
82+ private taskRunProcessProvider : TaskRunProcessProvider ;
8083
8184 constructor ( opts : RunExecutionOptions ) {
8285 this . id = randomBytes ( 4 ) . toString ( "hex" ) ;
@@ -85,6 +88,7 @@ export class RunExecution {
8588 this . httpClient = opts . httpClient ;
8689 this . logger = opts . logger ;
8790 this . supervisorSocket = opts . supervisorSocket ;
91+ this . taskRunProcessProvider = opts . taskRunProcessProvider ;
8892
8993 this . restoreCount = 0 ;
9094 this . executionAbortController = new AbortController ( ) ;
@@ -131,40 +135,21 @@ export class RunExecution {
131135 throw new Error ( "prepareForExecution called after process was already created" ) ;
132136 }
133137
134- this . taskRunProcess = this . createTaskRunProcess ( {
135- envVars : opts . taskRunEnv ,
138+ this . taskRunProcess = this . taskRunProcessProvider . getProcess ( {
139+ taskRunEnv : opts . taskRunEnv ,
136140 isWarmStart : true ,
137141 } ) ;
138142
143+ // Attach event handlers to the process
144+ this . attachTaskRunProcessHandlers ( this . taskRunProcess ) ;
145+
139146 return this ;
140147 }
141148
142- private createTaskRunProcess ( {
143- envVars,
144- isWarmStart,
145- } : {
146- envVars : Record < string , string > ;
147- isWarmStart ?: boolean ;
148- } ) {
149- const taskRunProcess = new TaskRunProcess ( {
150- workerManifest : this . workerManifest ,
151- env : {
152- ...envVars ,
153- ...this . env . gatherProcessEnv ( ) ,
154- HEARTBEAT_INTERVAL_MS : String ( this . env . TRIGGER_HEARTBEAT_INTERVAL_SECONDS * 1000 ) ,
155- } ,
156- serverWorker : {
157- id : "managed" ,
158- contentHash : this . env . TRIGGER_CONTENT_HASH ,
159- version : this . env . TRIGGER_DEPLOYMENT_VERSION ,
160- engine : "V2" ,
161- } ,
162- machineResources : {
163- cpu : Number ( this . env . TRIGGER_MACHINE_CPU ) ,
164- memory : Number ( this . env . TRIGGER_MACHINE_MEMORY ) ,
165- } ,
166- isWarmStart,
167- } ) . initialize ( ) ;
149+ private attachTaskRunProcessHandlers ( taskRunProcess : TaskRunProcess ) : void {
150+ taskRunProcess . onTaskRunHeartbeat . detach ( ) ;
151+ taskRunProcess . onSendDebugLog . detach ( ) ;
152+ taskRunProcess . onSetSuspendable . detach ( ) ;
168153
169154 taskRunProcess . onTaskRunHeartbeat . attach ( async ( runId ) => {
170155 if ( ! this . runFriendlyId ) {
@@ -194,8 +179,6 @@ export class RunExecution {
194179 taskRunProcess . onSetSuspendable . attach ( async ( { suspendable } ) => {
195180 this . suspendable = suspendable ;
196181 } ) ;
197-
198- return taskRunProcess ;
199182 }
200183
201184 /**
@@ -586,10 +569,11 @@ export class RunExecution {
586569
587570 // To skip this step and eagerly create the task run process, run prepareForExecution first
588571 if ( ! this . taskRunProcess || ! this . taskRunProcess . isPreparedForNextRun ) {
589- this . taskRunProcess = this . createTaskRunProcess ( {
590- envVars : { ...envVars , TRIGGER_PROJECT_REF : execution . project . ref } ,
572+ this . taskRunProcess = this . taskRunProcessProvider . getProcess ( {
573+ taskRunEnv : { ...envVars , TRIGGER_PROJECT_REF : execution . project . ref } ,
591574 isWarmStart,
592575 } ) ;
576+ this . attachTaskRunProcessHandlers ( this . taskRunProcess ) ;
593577 }
594578
595579 this . sendDebugLog ( "executing task run process" , { runId : execution . run . id } ) ;
@@ -619,7 +603,10 @@ export class RunExecution {
619603 // If we get here, the task completed normally
620604 this . sendDebugLog ( "completed run attempt" , { attemptSuccess : completion . ok } ) ;
621605
622- // The execution has finished, so we can cleanup the task run process. Killing it should be safe.
606+ // Return the process to the provider for potential reuse
607+ this . taskRunProcessProvider . returnProcess ( this . taskRunProcess ) ;
608+
609+ // The execution has finished, so we can cleanup the task run process if not being reused
623610 const [ error ] = await tryCatch ( this . taskRunProcess . cleanup ( true ) ) ;
624611
625612 if ( error ) {
0 commit comments