nx 21.0.0-canary.20250422-8619c1d → 21.0.0-canary.20250424-e23b25f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/package.json +11 -11
  2. package/src/command-line/init/configure-plugins.js +5 -3
  3. package/src/command-line/init/implementation/utils.d.ts +2 -1
  4. package/src/command-line/init/implementation/utils.js +2 -1
  5. package/src/command-line/init/init-v2.js +8 -7
  6. package/src/core/graph/main.js +1 -1
  7. package/src/executors/run-commands/run-commands.impl.d.ts +1 -2
  8. package/src/executors/run-commands/run-commands.impl.js +1 -1
  9. package/src/executors/run-commands/running-tasks.d.ts +5 -2
  10. package/src/executors/run-commands/running-tasks.js +42 -6
  11. package/src/native/index.d.ts +4 -1
  12. package/src/native/nx.wasm32-wasi.wasm +0 -0
  13. package/src/tasks-runner/default-tasks-runner.js +1 -1
  14. package/src/tasks-runner/forked-process-task-runner.js +3 -0
  15. package/src/tasks-runner/init-tasks-runner.js +2 -1
  16. package/src/tasks-runner/life-cycle.d.ts +6 -2
  17. package/src/tasks-runner/life-cycle.js +16 -2
  18. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.d.ts +2 -1
  19. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +16 -10
  20. package/src/tasks-runner/run-command.d.ts +2 -1
  21. package/src/tasks-runner/run-command.js +14 -6
  22. package/src/tasks-runner/running-tasks/node-child-process.js +4 -11
  23. package/src/tasks-runner/running-tasks/running-task.d.ts +3 -0
  24. package/src/tasks-runner/running-tasks/shared-running-task.d.ts +14 -0
  25. package/src/tasks-runner/running-tasks/shared-running-task.js +30 -0
  26. package/src/tasks-runner/task-orchestrator.d.ts +6 -3
  27. package/src/tasks-runner/task-orchestrator.js +79 -23
  28. package/src/tasks-runner/tasks-runner.d.ts +1 -0
  29. package/src/tasks-runner/tasks-schedule.d.ts +1 -0
  30. package/src/tasks-runner/tasks-schedule.js +9 -0
  31. package/src/tasks-runner/utils.js +2 -0
@@ -21,11 +21,13 @@ const noop_child_process_1 = require("./running-tasks/noop-child-process");
21
21
  const task_env_1 = require("./task-env");
22
22
  const tasks_schedule_1 = require("./tasks-schedule");
23
23
  const utils_1 = require("./utils");
24
+ const shared_running_task_1 = require("./running-tasks/shared-running-task");
24
25
  class TaskOrchestrator {
25
26
  // endregion internal state
26
- constructor(hasher, initiatingProject, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, taskGraphForHashing = taskGraph) {
27
+ constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, taskGraphForHashing = taskGraph) {
27
28
  this.hasher = hasher;
28
29
  this.initiatingProject = initiatingProject;
30
+ this.initiatingTasks = initiatingTasks;
29
31
  this.projectGraph = projectGraph;
30
32
  this.taskGraph = taskGraph;
31
33
  this.nxJson = nxJson;
@@ -43,6 +45,7 @@ class TaskOrchestrator {
43
45
  // region internal state
44
46
  this.batchEnv = (0, task_env_1.getEnvVariablesForBatchProcess)(this.options.skipNxCache, this.options.captureStderr);
45
47
  this.reverseTaskDeps = (0, utils_1.calculateReverseDeps)(this.taskGraph);
48
+ this.initializingTaskIds = new Set(this.initiatingTasks.map((t) => t.id));
46
49
  this.processedTasks = new Map();
47
50
  this.processedBatches = new Map();
48
51
  this.completedTasks = {};
@@ -50,7 +53,6 @@ class TaskOrchestrator {
50
53
  this.groups = [];
51
54
  this.bailed = false;
52
55
  this.runningContinuousTasks = new Map();
53
- this.cleaningUp = false;
54
56
  }
55
57
  async init() {
56
58
  // Init the ForkedProcessTaskRunner, TasksSchedule, and Cache
@@ -300,9 +302,17 @@ class TaskOrchestrator {
300
302
  const runningTask = await (0, run_commands_impl_1.runCommands)(runCommandsOptions, {
301
303
  root: workspace_root_1.workspaceRoot, // only root is needed in runCommands
302
304
  });
303
- if (this.tuiEnabled && runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
304
- // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
305
- this.options.lifeCycle.registerRunningTask(task.id, runningTask.getParserAndWriter());
305
+ if (this.tuiEnabled) {
306
+ if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
307
+ // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
308
+ this.options.lifeCycle.registerRunningTask(task.id, runningTask.getParserAndWriter());
309
+ }
310
+ else {
311
+ this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
312
+ runningTask.onOutput((output) => {
313
+ this.options.lifeCycle.appendTaskOutput(task.id, output);
314
+ });
315
+ }
306
316
  }
307
317
  if (!streamOutput) {
308
318
  if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
@@ -350,9 +360,17 @@ class TaskOrchestrator {
350
360
  else {
351
361
  // cache prep
352
362
  const runningTask = await this.runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput);
353
- if (this.tuiEnabled && runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
354
- // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
355
- this.options.lifeCycle.registerRunningTask(task.id, runningTask.getParserAndWriter());
363
+ if (this.tuiEnabled) {
364
+ if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
365
+ // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
366
+ this.options.lifeCycle.registerRunningTask(task.id, runningTask.getParserAndWriter());
367
+ }
368
+ else if ('onOutput' in runningTask) {
369
+ this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
370
+ runningTask.onOutput((output) => {
371
+ this.options.lifeCycle.appendTaskOutput(task.id, output);
372
+ });
373
+ }
356
374
  }
357
375
  return runningTask;
358
376
  }
@@ -397,15 +415,27 @@ class TaskOrchestrator {
397
415
  if (this.tuiEnabled) {
398
416
  this.options.lifeCycle.setTaskStatus(task.id, 8 /* NativeTaskStatus.Shared */);
399
417
  }
418
+ const runningTask = new shared_running_task_1.SharedRunningTask(this.runningTasksService, task.id);
419
+ this.runningContinuousTasks.set(task.id, runningTask);
420
+ runningTask.onExit(() => {
421
+ this.runningContinuousTasks.delete(task.id);
422
+ });
400
423
  // task is already running by another process, we schedule the next tasks
401
424
  // and release the threads
402
425
  await this.scheduleNextTasksAndReleaseThreads();
403
- // wait for the running task to finish
404
- do {
405
- console.log(`Waiting for ${task.id} in another nx process`);
406
- await new Promise((resolve) => setTimeout(resolve, 100));
407
- } while (this.runningTasksService.getRunningTasks([task.id]).length);
408
- return;
426
+ if (this.initializingTaskIds.has(task.id)) {
427
+ await new Promise((res) => {
428
+ runningTask.onExit((code) => {
429
+ if (!this.tuiEnabled) {
430
+ if (code > 128) {
431
+ process.exit(code);
432
+ }
433
+ }
434
+ res();
435
+ });
436
+ });
437
+ }
438
+ return runningTask;
409
439
  }
410
440
  const taskSpecificEnv = await this.processedTasks.get(task.id);
411
441
  await this.preRunSteps([task], { groupId });
@@ -425,14 +455,20 @@ class TaskOrchestrator {
425
455
  this.runningContinuousTasks.set(task.id, childProcess);
426
456
  childProcess.onExit(() => {
427
457
  this.runningTasksService.removeRunningTask(task.id);
458
+ this.runningContinuousTasks.delete(task.id);
428
459
  });
429
- if (this.initiatingProject === task.target.project &&
430
- this.options.targets.length === 1 &&
431
- this.options.targets[0] === task.target.target) {
432
- await childProcess.getResults();
433
- }
434
- else {
435
- await this.scheduleNextTasksAndReleaseThreads();
460
+ await this.scheduleNextTasksAndReleaseThreads();
461
+ if (this.initializingTaskIds.has(task.id)) {
462
+ await new Promise((res) => {
463
+ childProcess.onExit((code) => {
464
+ if (!this.tuiEnabled) {
465
+ if (code > 128) {
466
+ process.exit(code);
467
+ }
468
+ }
469
+ res();
470
+ });
471
+ });
436
472
  }
437
473
  return childProcess;
438
474
  }
@@ -505,6 +541,7 @@ class TaskOrchestrator {
505
541
  }
506
542
  complete(taskResults) {
507
543
  this.tasksSchedule.complete(taskResults.map(({ taskId }) => taskId));
544
+ this.cleanUpUnneededContinuousTasks();
508
545
  for (const { taskId, status } of taskResults) {
509
546
  if (this.completedTasks[taskId] === undefined) {
510
547
  this.completedTasks[taskId] = status;
@@ -571,10 +608,10 @@ class TaskOrchestrator {
571
608
  }
572
609
  // endregion utils
573
610
  async cleanup() {
574
- this.cleaningUp = true;
575
611
  await Promise.all(Array.from(this.runningContinuousTasks).map(async ([taskId, t]) => {
576
612
  try {
577
- return t.kill();
613
+ await t.kill();
614
+ this.options.lifeCycle.setTaskStatus(taskId, 9 /* NativeTaskStatus.Stopped */);
578
615
  }
579
616
  catch (e) {
580
617
  console.error(`Unable to terminate ${taskId}\nError:`, e);
@@ -584,6 +621,25 @@ class TaskOrchestrator {
584
621
  }
585
622
  }));
586
623
  }
624
+ cleanUpUnneededContinuousTasks() {
625
+ const incompleteTasks = this.tasksSchedule.getIncompleteTasks();
626
+ const neededContinuousTasks = new Set(this.initializingTaskIds);
627
+ for (const task of incompleteTasks) {
628
+ const continuousDependencies = this.taskGraph.continuousDependencies[task.id];
629
+ for (const continuousDependency of continuousDependencies) {
630
+ neededContinuousTasks.add(continuousDependency);
631
+ }
632
+ }
633
+ for (const taskId of this.runningContinuousTasks.keys()) {
634
+ if (!neededContinuousTasks.has(taskId)) {
635
+ const runningTask = this.runningContinuousTasks.get(taskId);
636
+ if (runningTask) {
637
+ runningTask.kill();
638
+ this.options.lifeCycle.setTaskStatus(taskId, 9 /* NativeTaskStatus.Stopped */);
639
+ }
640
+ }
641
+ }
642
+ }
587
643
  }
588
644
  exports.TaskOrchestrator = TaskOrchestrator;
589
645
  function getThreadCount(options, taskGraph) {
@@ -12,6 +12,7 @@ export type TaskStatus = 'success' | 'failure' | 'skipped' | 'local-cache-kept-e
12
12
  export type TasksRunner<T = unknown> = (tasks: Task[], options: T, context?: {
13
13
  target?: string;
14
14
  initiatingProject?: string | null;
15
+ initiatingTasks: Task[];
15
16
  projectGraph: ProjectGraph;
16
17
  nxJson: NxJsonConfiguration;
17
18
  nxArgs: NxArgs;
@@ -31,6 +31,7 @@ export declare class TasksSchedule {
31
31
  };
32
32
  nextTask(): Task;
33
33
  nextBatch(): Batch;
34
+ getIncompleteTasks(): Task[];
34
35
  private scheduleTasks;
35
36
  private scheduleTask;
36
37
  private scheduleBatches;
@@ -68,6 +68,15 @@ class TasksSchedule {
68
68
  ? this.scheduledBatches.shift()
69
69
  : null;
70
70
  }
71
+ getIncompleteTasks() {
72
+ const incompleteTasks = [];
73
+ for (const taskId in this.taskGraph.tasks) {
74
+ if (!this.completedTasks.has(taskId)) {
75
+ incompleteTasks.push(this.taskGraph.tasks[taskId]);
76
+ }
77
+ }
78
+ return incompleteTasks;
79
+ }
71
80
  async scheduleTasks() {
72
81
  if (this.options.batch || process.env.NX_BATCH_MODE === 'true') {
73
82
  await this.scheduleBatches();
@@ -374,6 +374,8 @@ function shouldStreamOutput(task, initiatingProject) {
374
374
  return false;
375
375
  if (process.env.NX_STREAM_OUTPUT === 'true')
376
376
  return true;
377
+ if (process.env.NX_STREAM_OUTPUT === 'false')
378
+ return false;
377
379
  if (longRunningTask(task))
378
380
  return true;
379
381
  if (task.target.project === initiatingProject)