@@ -35,10 +35,26 @@ export class TaskRunProcessProvider {
35
35
this . processKeepAliveMaxExecutionCount = opts . processKeepAliveMaxExecutionCount ;
36
36
}
37
37
38
+ async handleImmediateRetry ( ) : Promise < void > {
39
+ if ( ! this . processKeepAliveEnabled ) {
40
+ // For immediate retries, we need to ensure we have a clean process
41
+ if ( this . persistentProcess ) {
42
+ // If the process is not prepared for the next attempt, we need to get a fresh one
43
+ if ( ! this . persistentProcess . isPreparedForNextAttempt ) {
44
+ this . sendDebugLog (
45
+ "existing task run process not prepared for retry, will get fresh process"
46
+ ) ;
47
+ await this . persistentProcess . kill ( "SIGKILL" ) ;
48
+ this . persistentProcess = null ;
49
+ }
50
+ }
51
+ }
52
+ }
53
+
38
54
/**
39
55
* Gets a TaskRunProcess, either by reusing an existing one or creating a new one
40
56
*/
41
- getProcess ( opts : GetProcessOptions ) : TaskRunProcess {
57
+ async getProcess ( opts : GetProcessOptions ) : Promise < TaskRunProcess > {
42
58
this . sendDebugLog ( "Getting TaskRunProcess" , {
43
59
processKeepAliveEnabled : this . processKeepAliveEnabled ,
44
60
hasPersistentProcess : ! ! this . persistentProcess ,
@@ -47,16 +63,22 @@ export class TaskRunProcessProvider {
47
63
isWarmStart : opts . isWarmStart ,
48
64
} ) ;
49
65
66
+ // If process keep-alive is disabled, always create a new process
67
+ if ( ! this . processKeepAliveEnabled ) {
68
+ this . sendDebugLog ( "Creating new TaskRunProcess (keep-alive disabled)" ) ;
69
+ return this . createTaskRunProcess ( opts ) ;
70
+ }
71
+
50
72
// If process keep-alive is enabled and we have a healthy persistent process, reuse it
51
- if ( this . processKeepAliveEnabled && this . shouldReusePersistentProcess ( ) ) {
73
+ if ( this . shouldReusePersistentProcess ( ) ) {
52
74
this . sendDebugLog ( "Reusing persistent TaskRunProcess" , {
53
75
executionCount : this . executionCount ,
54
76
} ) ;
55
77
56
78
return this . persistentProcess ! ;
57
79
}
58
80
59
- // Create new process
81
+ // Create new process (keep-alive enabled but no reusable process available)
60
82
this . sendDebugLog ( "Creating new TaskRunProcess" , {
61
83
hadPersistentProcess : ! ! this . persistentProcess ,
62
84
reason : this . processKeepAliveEnabled
@@ -66,41 +88,69 @@ export class TaskRunProcessProvider {
66
88
67
89
// Clean up old persistent process if it exists
68
90
if ( this . persistentProcess ) {
69
- this . cleanupPersistentProcess ( ) ;
91
+ await this . cleanupPersistentProcess ( ) ;
70
92
}
71
93
72
94
const newProcess = this . createTaskRunProcess ( opts ) ;
73
95
return newProcess ;
74
96
}
75
97
76
98
/**
77
- * Returns a process after execution, handling keep-alive logic
99
+ * Returns a process after execution, handling keep-alive logic and cleanup
78
100
*/
79
- returnProcess ( process : TaskRunProcess ) : void {
101
+ async returnProcess ( process : TaskRunProcess ) : Promise < void > {
102
+ this . sendDebugLog ( "Returning TaskRunProcess" , {
103
+ processKeepAliveEnabled : this . processKeepAliveEnabled ,
104
+ executionCount : this . executionCount ,
105
+ maxExecutionCount : this . processKeepAliveMaxExecutionCount ,
106
+ } ) ;
107
+
80
108
if ( ! this . processKeepAliveEnabled ) {
81
- this . sendDebugLog ( "Keep-alive disabled, not preserving process" ) ;
109
+ // Keep-alive disabled - immediately cleanup the process
110
+ this . sendDebugLog ( "Keep-alive disabled, cleaning up process immediately" ) ;
111
+ await process . cleanup ( true ) ;
82
112
return ;
83
113
}
84
114
115
+ // Keep-alive enabled - check if we should keep the process alive
85
116
if ( this . shouldKeepProcessAlive ( process ) ) {
86
117
this . sendDebugLog ( "Keeping TaskRunProcess alive for next run" , {
87
118
executionCount : this . executionCount ,
88
119
maxExecutionCount : this . processKeepAliveMaxExecutionCount ,
89
120
} ) ;
90
121
122
+ // Call cleanup(false) to prepare for next run but keep process alive
123
+ await process . cleanup ( false ) ;
91
124
this . persistentProcess = process ;
92
125
this . executionCount ++ ;
93
126
} else {
94
- this . sendDebugLog ( "Not keeping TaskRunProcess alive" , {
127
+ this . sendDebugLog ( "Not keeping TaskRunProcess alive, cleaning up " , {
95
128
executionCount : this . executionCount ,
96
129
maxExecutionCount : this . processKeepAliveMaxExecutionCount ,
97
130
isHealthy : this . isProcessHealthy ( process ) ,
98
131
} ) ;
99
132
100
- // Don't set as persistent, it will be cleaned up normally
133
+ // Cleanup the process completely
134
+ await process . cleanup ( true ) ;
101
135
}
102
136
}
103
137
138
+ /**
139
+ * Handles process abort/kill scenarios
140
+ */
141
+ async handleProcessAbort ( process : TaskRunProcess ) : Promise < void > {
142
+ this . sendDebugLog ( "Handling process abort" ) ;
143
+
144
+ // If this was our persistent process, clear it
145
+ if ( this . persistentProcess ?. pid === process . pid ) {
146
+ this . persistentProcess = null ;
147
+ this . executionCount = 0 ;
148
+ }
149
+
150
+ // Kill the process
151
+ await process . cleanup ( true ) ;
152
+ }
153
+
104
154
/**
105
155
* Forces cleanup of any persistent process
106
156
*/
@@ -173,12 +223,12 @@ export class TaskRunProcessProvider {
173
223
return process . isPreparedForNextRun || process . isPreparedForNextAttempt ;
174
224
}
175
225
176
- private cleanupPersistentProcess ( ) : void {
226
+ private async cleanupPersistentProcess ( ) : Promise < void > {
177
227
if ( this . persistentProcess ) {
178
228
this . sendDebugLog ( "Cleaning up persistent TaskRunProcess" ) ;
179
229
180
230
// Don't await this - let it cleanup in the background
181
- this . persistentProcess . kill ( "SIGKILL" ) . catch ( ( ) => { } ) ;
231
+ await this . persistentProcess . kill ( "SIGKILL" ) . catch ( ( ) => { } ) ;
182
232
this . persistentProcess = null ;
183
233
this . executionCount = 0 ;
184
234
}
0 commit comments