@@ -22,6 +22,7 @@ import { randomBytes } from "node:crypto";
22
22
import { SnapshotManager , SnapshotState } from "./snapshot.js" ;
23
23
import type { SupervisorSocket } from "./controller.js" ;
24
24
import { RunNotifier } from "./notifier.js" ;
25
+ import { TaskRunProcessProvider } from "./taskRunProcessProvider.js" ;
25
26
26
27
class ExecutionAbortError extends Error {
27
28
constructor ( message : string ) {
@@ -36,6 +37,7 @@ type RunExecutionOptions = {
36
37
httpClient : WorkloadHttpClient ;
37
38
logger : RunLogger ;
38
39
supervisorSocket : SupervisorSocket ;
40
+ taskRunProcessProvider : TaskRunProcessProvider ;
39
41
} ;
40
42
41
43
type RunExecutionPrepareOptions = {
@@ -77,6 +79,7 @@ export class RunExecution {
77
79
private supervisorSocket : SupervisorSocket ;
78
80
private notifier ?: RunNotifier ;
79
81
private metadataClient ?: MetadataClient ;
82
+ private taskRunProcessProvider : TaskRunProcessProvider ;
80
83
81
84
constructor ( opts : RunExecutionOptions ) {
82
85
this . id = randomBytes ( 4 ) . toString ( "hex" ) ;
@@ -85,6 +88,7 @@ export class RunExecution {
85
88
this . httpClient = opts . httpClient ;
86
89
this . logger = opts . logger ;
87
90
this . supervisorSocket = opts . supervisorSocket ;
91
+ this . taskRunProcessProvider = opts . taskRunProcessProvider ;
88
92
89
93
this . restoreCount = 0 ;
90
94
this . executionAbortController = new AbortController ( ) ;
@@ -131,40 +135,21 @@ export class RunExecution {
131
135
throw new Error ( "prepareForExecution called after process was already created" ) ;
132
136
}
133
137
134
- this . taskRunProcess = this . createTaskRunProcess ( {
135
- envVars : opts . taskRunEnv ,
138
+ this . taskRunProcess = this . taskRunProcessProvider . getProcess ( {
139
+ taskRunEnv : opts . taskRunEnv ,
136
140
isWarmStart : true ,
137
141
} ) ;
138
142
143
+ // Attach event handlers to the process
144
+ this . attachTaskRunProcessHandlers ( this . taskRunProcess ) ;
145
+
139
146
return this ;
140
147
}
141
148
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 ( ) ;
168
153
169
154
taskRunProcess . onTaskRunHeartbeat . attach ( async ( runId ) => {
170
155
if ( ! this . runFriendlyId ) {
@@ -194,8 +179,6 @@ export class RunExecution {
194
179
taskRunProcess . onSetSuspendable . attach ( async ( { suspendable } ) => {
195
180
this . suspendable = suspendable ;
196
181
} ) ;
197
-
198
- return taskRunProcess ;
199
182
}
200
183
201
184
/**
@@ -586,10 +569,11 @@ export class RunExecution {
586
569
587
570
// To skip this step and eagerly create the task run process, run prepareForExecution first
588
571
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 } ,
591
574
isWarmStart,
592
575
} ) ;
576
+ this . attachTaskRunProcessHandlers ( this . taskRunProcess ) ;
593
577
}
594
578
595
579
this . sendDebugLog ( "executing task run process" , { runId : execution . run . id } ) ;
@@ -619,7 +603,10 @@ export class RunExecution {
619
603
// If we get here, the task completed normally
620
604
this . sendDebugLog ( "completed run attempt" , { attemptSuccess : completion . ok } ) ;
621
605
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
623
610
const [ error ] = await tryCatch ( this . taskRunProcess . cleanup ( true ) ) ;
624
611
625
612
if ( error ) {
0 commit comments