@@ -124,16 +124,22 @@ func (o *Orchestrator) ScheduleOrder() []string {
124124// picked up may not be done yet, so a builder can take a dependent of a slow project and
125125// wait on that project while a later project's upstream has already finished. The stable
126126// sort preserves the original order within a depth, and reporting still follows Order().
127- func (o * Orchestrator ) computeScheduleOrder () []* BuildTask {
127+ func (o * Orchestrator ) computeScheduleOrder (ctx context. Context ) []* BuildTask {
128128 type scheduleEntry struct {
129129 task * BuildTask
130130 depth int
131131 }
132132 entries := make ([]scheduleEntry , len (o .order ))
133133 depths := make (map [* BuildTask ]int , len (o .order ))
134134 for i , task := range o .order {
135+ if ctx .Err () != nil {
136+ return nil
137+ }
135138 depth := 0
136139 for _ , upstream := range task .upStream {
140+ if ctx .Err () != nil {
141+ return nil
142+ }
137143 depth = max (depth , depths [upstream .task ]+ 1 )
138144 }
139145 depths [task ] = depth
@@ -142,9 +148,14 @@ func (o *Orchestrator) computeScheduleOrder() []*BuildTask {
142148 slices .SortStableFunc (entries , func (a , b scheduleEntry ) int {
143149 return a .depth - b .depth
144150 })
145- return core .Map (entries , func (entry scheduleEntry ) * BuildTask {
146- return entry .task
147- })
151+ order := make ([]* BuildTask , len (entries ))
152+ for i , entry := range entries {
153+ if ctx .Err () != nil {
154+ return nil
155+ }
156+ order [i ] = entry .task
157+ }
158+ return order
148159}
149160
150161func (o * Orchestrator ) Upstream (configName string ) []string {
@@ -171,9 +182,15 @@ func (o *Orchestrator) getTask(path tspath.PathKey) *BuildTask {
171182 return task
172183}
173184
174- func (o * Orchestrator ) createBuildTasks (oldTasks * collections.SyncMap [tspath.PathKey , * BuildTask ], configs []tspath.RootedFilePath , wg core.WorkGroup ) {
185+ func (o * Orchestrator ) createBuildTasks (ctx context. Context , oldTasks * collections.SyncMap [tspath.PathKey , * BuildTask ], configs []tspath.RootedFilePath , wg core.WorkGroup ) {
175186 for _ , config := range configs {
187+ if ctx .Err () != nil {
188+ return
189+ }
176190 wg .Queue (func () {
191+ if ctx .Err () != nil {
192+ return
193+ }
177194 path := o .caseSensitivity .PathKey (tspath .RootedPath (config ))
178195 var task * BuildTask
179196 var buildInfo * buildInfoEntry
@@ -201,20 +218,24 @@ func (o *Orchestrator) createBuildTasks(oldTasks *collections.SyncMap[tspath.Pat
201218 task .resolved = o .host .GetResolvedProjectReference (config , path )
202219 task .upStream = nil
203220 if task .resolved != nil {
204- o .createBuildTasks (oldTasks , task .resolved .ResolvedProjectReferencePaths (), wg )
221+ o .createBuildTasks (ctx , oldTasks , task .resolved .ResolvedProjectReferencePaths (), wg )
205222 }
206223 })
207224 }
208225}
209226
210227func (o * Orchestrator ) setupBuildTask (
228+ ctx context.Context ,
211229 configName tspath.RootedFilePath ,
212230 downStream * BuildTask ,
213231 inCircularContext bool ,
214232 completed * collections.Set [tspath.PathKey ],
215233 analyzing * collections.Set [tspath.PathKey ],
216234 circularityStack []string ,
217235) * BuildTask {
236+ if ctx .Err () != nil {
237+ return nil
238+ }
218239 path := o .caseSensitivity .PathKey (tspath .RootedPath (configName ))
219240 task := o .getTask (path )
220241 if ! completed .Has (path ) {
@@ -231,7 +252,10 @@ func (o *Orchestrator) setupBuildTask(
231252 circularityStack = append (circularityStack , configName .AsString ())
232253 if task .resolved != nil {
233254 for index , subReference := range task .resolved .ResolvedProjectReferencePaths () {
234- upstream := o .setupBuildTask (subReference , task , inCircularContext || task .resolved .ProjectReferences ()[index ].Circular , completed , analyzing , circularityStack )
255+ if ctx .Err () != nil {
256+ return nil
257+ }
258+ upstream := o .setupBuildTask (ctx , subReference , task , inCircularContext || task .resolved .ProjectReferences ()[index ].Circular , completed , analyzing , circularityStack )
235259 if upstream != nil {
236260 task .upStream = append (task .upStream , & upstreamTask {task : upstream , refIndex : index })
237261 }
@@ -249,41 +273,67 @@ func (o *Orchestrator) setupBuildTask(
249273 return task
250274}
251275
252- func (o * Orchestrator ) GenerateGraphReusingOldTasks () {
276+ func (o * Orchestrator ) GenerateGraphReusingOldTasks (ctx context. Context ) {
253277 tasks := o .tasks
254278 o .tasks = & collections.SyncMap [tspath.PathKey , * BuildTask ]{}
255279 o .order = nil
256280 o .errors = nil
257- o .GenerateGraph (tasks )
281+ o .GenerateGraph (ctx , tasks )
258282}
259283
260- func (o * Orchestrator ) GenerateGraph (oldTasks * collections.SyncMap [tspath.PathKey , * BuildTask ]) {
284+ func (o * Orchestrator ) GenerateGraph (ctx context.Context , oldTasks * collections.SyncMap [tspath.PathKey , * BuildTask ]) {
285+ o .graphGenerated = false
286+ defer func () {
287+ if oldTasks != nil {
288+ oldTasks .Range (func (path tspath.PathKey , oldTask * BuildTask ) bool {
289+ if task , ok := o .tasks .Load (path ); ok && task == oldTask {
290+ return true
291+ }
292+ if oldTask .contentMapperProject != nil {
293+ _ = oldTask .contentMapperProject .Close ()
294+ }
295+ return true
296+ })
297+ }
298+ if ctx .Err () != nil {
299+ // A partial graph must not be reused or built on a subsequent request.
300+ o .tasks .Range (func (_ tspath.PathKey , task * BuildTask ) bool {
301+ if task .contentMapperProject != nil {
302+ _ = task .contentMapperProject .Close ()
303+ }
304+ return true
305+ })
306+ o .tasks = & collections.SyncMap [tspath.PathKey , * BuildTask ]{}
307+ o .order = nil
308+ o .scheduleOrder = nil
309+ o .errors = nil
310+ o .graphGenerated = false
311+ }
312+ }()
313+ if ctx .Err () != nil {
314+ return
315+ }
261316 projects := o .opts .Command .ResolvedProjectPaths ()
262317 // Parse all config files in parallel
263318 wg := core .NewWorkGroup (o .opts .Command .CompilerOptions .SingleThreaded .IsTrue ())
264- o .createBuildTasks (oldTasks , projects , wg )
319+ o .createBuildTasks (ctx , oldTasks , projects , wg )
265320 wg .RunAndWait ()
321+ if ctx .Err () != nil {
322+ return
323+ }
266324
267325 // Generate the graph
268326 completed := collections.Set [tspath.PathKey ]{}
269327 analyzing := collections.Set [tspath.PathKey ]{}
270328 circularityStack := []string {}
271329 for _ , project := range projects {
272- o .setupBuildTask (project , nil , false , & completed , & analyzing , circularityStack )
273- }
274- o .scheduleOrder = o .computeScheduleOrder ()
275- if oldTasks != nil {
276- oldTasks .Range (func (path tspath.PathKey , oldTask * BuildTask ) bool {
277- if task , ok := o .tasks .Load (path ); ok && task == oldTask {
278- return true
279- }
280- if oldTask .contentMapperProject != nil {
281- _ = oldTask .contentMapperProject .Close ()
282- }
283- return true
284- })
330+ if ctx .Err () != nil {
331+ return
332+ }
333+ o .setupBuildTask (ctx , project , nil , false , & completed , & analyzing , circularityStack )
285334 }
286- o .graphGenerated = true
335+ o .scheduleOrder = o .computeScheduleOrder (ctx )
336+ o .graphGenerated = ctx .Err () == nil
287337}
288338
289339// tsc -b entrypoint
@@ -293,17 +343,20 @@ func (o *Orchestrator) Start(ctx context.Context) tsc.CommandLineResult {
293343
294344// orchestrator.Build() entrypoint for api
295345func (o * Orchestrator ) Build (ctx context.Context , project string ) * OrchestratorResult {
296- o .recheckAllProjects (project )
346+ o .recheckAllProjects (ctx , project )
297347 return o .start (ctx , project , false /*onlyReferences*/ )
298348}
299349
300350// orchestrator.BuildReferences() entrypoint for api
301351func (o * Orchestrator ) BuildReferences (ctx context.Context , project string ) * OrchestratorResult {
302- o .recheckAllProjects (project )
352+ o .recheckAllProjects (ctx , project )
303353 return o .start (ctx , project , true /*onlyReferences*/ )
304354}
305355
306356func (o * Orchestrator ) start (ctx context.Context , project string , onlyReferences bool ) * OrchestratorResult {
357+ if ctx .Err () != nil {
358+ return & OrchestratorResult {Result : tsc.CommandLineResult {Status : tsc .ExitStatusCancelled }}
359+ }
307360 o .contentMapperHost = tsc .NewContentMapperHost (ctx , o .opts .Sys , o .opts .Command .CompilerOptions )
308361 if o .contentMapperHost != nil && (! o .opts .Command .CompilerOptions .Watch .IsTrue () || o .opts .Testing == nil ) {
309362 defer o .contentMapperHost .Close ()
@@ -312,9 +365,12 @@ func (o *Orchestrator) start(ctx context.Context, project string, onlyReferences
312365 o .watchStatusReporter (ast .NewCompilerDiagnostic (diagnostics .Starting_compilation_in_watch_mode ))
313366 }
314367 if o .graphGenerated {
315- o .GenerateGraphReusingOldTasks ()
368+ o .GenerateGraphReusingOldTasks (ctx )
316369 } else {
317- o .GenerateGraph (nil )
370+ o .GenerateGraph (ctx , nil )
371+ }
372+ if ctx .Err () != nil {
373+ return & OrchestratorResult {Result : tsc.CommandLineResult {Status : tsc .ExitStatusCancelled }}
318374 }
319375 order , ok := o .getBuildOrderFor (project )
320376 if ! ok {
@@ -337,15 +393,18 @@ func (o *Orchestrator) start(ctx context.Context, project string, onlyReferences
337393 return result
338394}
339395
340- func (o * Orchestrator ) recheckAllProjects (project string ) {
341- if ! o .graphGenerated {
396+ func (o * Orchestrator ) recheckAllProjects (ctx context. Context , project string ) {
397+ if ! o .graphGenerated || ctx . Err () != nil {
342398 return
343399 }
344400 order , ok := o .getBuildOrderFor (project )
345401 if ! ok {
346402 return
347403 }
348404 o .rangeTasks (order , func (path tspath.PathKey , task * BuildTask ) {
405+ if ctx .Err () != nil {
406+ return
407+ }
349408 task .resetStatus ()
350409 task .resetConfig (o , path )
351410 })
@@ -365,7 +424,7 @@ func (o *Orchestrator) CleanReferences(project string) *OrchestratorResult {
365424
366425func (o * Orchestrator ) clean (project string , onlyReferences bool ) * OrchestratorResult {
367426 if ! o .graphGenerated {
368- o .GenerateGraph (nil )
427+ o .GenerateGraph (context . Background (), nil )
369428 }
370429 if len (o .errors ) != 0 {
371430 result := & OrchestratorResult {
@@ -854,10 +913,16 @@ func (o *Orchestrator) DoCycle(ctx context.Context) {
854913 o .watchStatusReporter (ast .NewCompilerDiagnostic (diagnostics .File_change_detected_Starting_incremental_compilation ))
855914 if needsConfigUpdate .Load () {
856915 // Generate new tasks
857- o .GenerateGraphReusingOldTasks ()
916+ o .GenerateGraphReusingOldTasks (ctx )
917+ }
918+ if ctx .Err () != nil {
919+ return
858920 }
859921
860922 o .buildOrClean (ctx )
923+ if ctx .Err () != nil {
924+ return
925+ }
861926 o .updateWatch ()
862927 desiredDirs := o .computeDesiredWatches ()
863928 if err := o .wm .ReconcileWatches (desiredDirs ); err != nil {
0 commit comments