@rushstack/operation-graph 0.5.7 → 0.6.1

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 (76) hide show
  1. package/CHANGELOG.json +40 -0
  2. package/CHANGELOG.md +15 -1
  3. package/dist/tsdoc-metadata.json +1 -1
  4. package/lib-esm/IOperationRunner.js +4 -0
  5. package/lib-esm/IOperationRunner.js.map +1 -0
  6. package/lib-esm/Operation.js +218 -0
  7. package/lib-esm/Operation.js.map +1 -0
  8. package/lib-esm/OperationError.js +25 -0
  9. package/lib-esm/OperationError.js.map +1 -0
  10. package/lib-esm/OperationExecutionManager.js +138 -0
  11. package/lib-esm/OperationExecutionManager.js.map +1 -0
  12. package/lib-esm/OperationGroupRecord.js +62 -0
  13. package/lib-esm/OperationGroupRecord.js.map +1 -0
  14. package/lib-esm/OperationStatus.js +42 -0
  15. package/lib-esm/OperationStatus.js.map +1 -0
  16. package/lib-esm/Stopwatch.js +93 -0
  17. package/lib-esm/Stopwatch.js.map +1 -0
  18. package/lib-esm/WatchLoop.js +210 -0
  19. package/lib-esm/WatchLoop.js.map +1 -0
  20. package/lib-esm/WorkQueue.js +49 -0
  21. package/lib-esm/WorkQueue.js.map +1 -0
  22. package/lib-esm/calculateCriticalPath.js +83 -0
  23. package/lib-esm/calculateCriticalPath.js.map +1 -0
  24. package/lib-esm/index.js +10 -0
  25. package/lib-esm/index.js.map +1 -0
  26. package/lib-esm/protocol.types.js +4 -0
  27. package/lib-esm/protocol.types.js.map +1 -0
  28. package/package.json +30 -6
  29. /package/{lib → lib-commonjs}/IOperationRunner.js +0 -0
  30. /package/{lib → lib-commonjs}/IOperationRunner.js.map +0 -0
  31. /package/{lib → lib-commonjs}/Operation.js +0 -0
  32. /package/{lib → lib-commonjs}/Operation.js.map +0 -0
  33. /package/{lib → lib-commonjs}/OperationError.js +0 -0
  34. /package/{lib → lib-commonjs}/OperationError.js.map +0 -0
  35. /package/{lib → lib-commonjs}/OperationExecutionManager.js +0 -0
  36. /package/{lib → lib-commonjs}/OperationExecutionManager.js.map +0 -0
  37. /package/{lib → lib-commonjs}/OperationGroupRecord.js +0 -0
  38. /package/{lib → lib-commonjs}/OperationGroupRecord.js.map +0 -0
  39. /package/{lib → lib-commonjs}/OperationStatus.js +0 -0
  40. /package/{lib → lib-commonjs}/OperationStatus.js.map +0 -0
  41. /package/{lib → lib-commonjs}/Stopwatch.js +0 -0
  42. /package/{lib → lib-commonjs}/Stopwatch.js.map +0 -0
  43. /package/{lib → lib-commonjs}/WatchLoop.js +0 -0
  44. /package/{lib → lib-commonjs}/WatchLoop.js.map +0 -0
  45. /package/{lib → lib-commonjs}/WorkQueue.js +0 -0
  46. /package/{lib → lib-commonjs}/WorkQueue.js.map +0 -0
  47. /package/{lib → lib-commonjs}/calculateCriticalPath.js +0 -0
  48. /package/{lib → lib-commonjs}/calculateCriticalPath.js.map +0 -0
  49. /package/{lib → lib-commonjs}/index.js +0 -0
  50. /package/{lib → lib-commonjs}/index.js.map +0 -0
  51. /package/{lib → lib-commonjs}/protocol.types.js +0 -0
  52. /package/{lib → lib-commonjs}/protocol.types.js.map +0 -0
  53. /package/{lib → lib-dts}/IOperationRunner.d.ts +0 -0
  54. /package/{lib → lib-dts}/IOperationRunner.d.ts.map +0 -0
  55. /package/{lib → lib-dts}/Operation.d.ts +0 -0
  56. /package/{lib → lib-dts}/Operation.d.ts.map +0 -0
  57. /package/{lib → lib-dts}/OperationError.d.ts +0 -0
  58. /package/{lib → lib-dts}/OperationError.d.ts.map +0 -0
  59. /package/{lib → lib-dts}/OperationExecutionManager.d.ts +0 -0
  60. /package/{lib → lib-dts}/OperationExecutionManager.d.ts.map +0 -0
  61. /package/{lib → lib-dts}/OperationGroupRecord.d.ts +0 -0
  62. /package/{lib → lib-dts}/OperationGroupRecord.d.ts.map +0 -0
  63. /package/{lib → lib-dts}/OperationStatus.d.ts +0 -0
  64. /package/{lib → lib-dts}/OperationStatus.d.ts.map +0 -0
  65. /package/{lib → lib-dts}/Stopwatch.d.ts +0 -0
  66. /package/{lib → lib-dts}/Stopwatch.d.ts.map +0 -0
  67. /package/{lib → lib-dts}/WatchLoop.d.ts +0 -0
  68. /package/{lib → lib-dts}/WatchLoop.d.ts.map +0 -0
  69. /package/{lib → lib-dts}/WorkQueue.d.ts +0 -0
  70. /package/{lib → lib-dts}/WorkQueue.d.ts.map +0 -0
  71. /package/{lib → lib-dts}/calculateCriticalPath.d.ts +0 -0
  72. /package/{lib → lib-dts}/calculateCriticalPath.d.ts.map +0 -0
  73. /package/{lib → lib-dts}/index.d.ts +0 -0
  74. /package/{lib → lib-dts}/index.d.ts.map +0 -0
  75. /package/{lib → lib-dts}/protocol.types.d.ts +0 -0
  76. /package/{lib → lib-dts}/protocol.types.d.ts.map +0 -0
@@ -0,0 +1,42 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ /**
4
+ * Enumeration defining potential states of an operation
5
+ * @beta
6
+ */
7
+ export var OperationStatus;
8
+ (function (OperationStatus) {
9
+ /**
10
+ * The Operation is on the queue, ready to execute
11
+ */
12
+ OperationStatus["Ready"] = "READY";
13
+ /**
14
+ * The Operation is on the queue, waiting for one or more depencies
15
+ */
16
+ OperationStatus["Waiting"] = "WAITING";
17
+ /**
18
+ * The Operation is currently executing
19
+ */
20
+ OperationStatus["Executing"] = "EXECUTING";
21
+ /**
22
+ * The Operation completed successfully and did not write to standard output
23
+ */
24
+ OperationStatus["Success"] = "SUCCESS";
25
+ /**
26
+ * The Operation failed
27
+ */
28
+ OperationStatus["Failure"] = "FAILURE";
29
+ /**
30
+ * The operation was aborted
31
+ */
32
+ OperationStatus["Aborted"] = "ABORTED";
33
+ /**
34
+ * The Operation could not be executed because one or more of its dependencies failed
35
+ */
36
+ OperationStatus["Blocked"] = "BLOCKED";
37
+ /**
38
+ * The operation performed no meaningful work.
39
+ */
40
+ OperationStatus["NoOp"] = "NO OP";
41
+ })(OperationStatus || (OperationStatus = {}));
42
+ //# sourceMappingURL=OperationStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OperationStatus.js","sourceRoot":"","sources":["../src/OperationStatus.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D;;;GAGG;AACH,MAAM,CAAN,IAAY,eAiCX;AAjCD,WAAY,eAAe;IACzB;;OAEG;IACH,kCAAe,CAAA;IACf;;OAEG;IACH,sCAAmB,CAAA;IACnB;;OAEG;IACH,0CAAuB,CAAA;IACvB;;OAEG;IACH,sCAAmB,CAAA;IACnB;;OAEG;IACH,sCAAmB,CAAA;IACnB;;OAEG;IACH,sCAAmB,CAAA;IACnB;;OAEG;IACH,sCAAmB,CAAA;IACnB;;OAEG;IACH,iCAAc,CAAA;AAChB,CAAC,EAjCW,eAAe,KAAf,eAAe,QAiC1B","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * Enumeration defining potential states of an operation\n * @beta\n */\nexport enum OperationStatus {\n /**\n * The Operation is on the queue, ready to execute\n */\n Ready = 'READY',\n /**\n * The Operation is on the queue, waiting for one or more depencies\n */\n Waiting = 'WAITING',\n /**\n * The Operation is currently executing\n */\n Executing = 'EXECUTING',\n /**\n * The Operation completed successfully and did not write to standard output\n */\n Success = 'SUCCESS',\n /**\n * The Operation failed\n */\n Failure = 'FAILURE',\n /**\n * The operation was aborted\n */\n Aborted = 'ABORTED',\n /**\n * The Operation could not be executed because one or more of its dependencies failed\n */\n Blocked = 'BLOCKED',\n /**\n * The operation performed no meaningful work.\n */\n NoOp = 'NO OP'\n}\n"]}
@@ -0,0 +1,93 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ /**
4
+ * Represents a typical timer/stopwatch which keeps track
5
+ * of elapsed time in between two events.
6
+ *
7
+ * @public
8
+ */
9
+ export class Stopwatch {
10
+ constructor() {
11
+ this._startTime = undefined;
12
+ this._endTime = undefined;
13
+ this._running = false;
14
+ }
15
+ /**
16
+ * Static helper function which creates a stopwatch which is immediately started
17
+ */
18
+ static start() {
19
+ return new Stopwatch().start();
20
+ }
21
+ get isRunning() {
22
+ return this._running;
23
+ }
24
+ /**
25
+ * Starts the stopwatch. Note that if end() has been called,
26
+ * reset() should be called before calling start() again.
27
+ */
28
+ start() {
29
+ if (this._startTime !== undefined) {
30
+ throw new Error('Call reset() before starting the Stopwatch');
31
+ }
32
+ this._startTime = performance.now();
33
+ this._endTime = undefined;
34
+ this._running = true;
35
+ return this;
36
+ }
37
+ /**
38
+ * Stops executing the stopwatch and saves the current timestamp
39
+ */
40
+ stop() {
41
+ this._endTime = this._startTime !== undefined ? performance.now() : undefined;
42
+ this._running = false;
43
+ return this;
44
+ }
45
+ /**
46
+ * Resets all values of the stopwatch back to the original
47
+ */
48
+ reset() {
49
+ this._endTime = this._startTime = undefined;
50
+ this._running = false;
51
+ return this;
52
+ }
53
+ /**
54
+ * Displays how long the stopwatch has been executing in a human readable format.
55
+ */
56
+ toString() {
57
+ if (!this._running && this._startTime === undefined) {
58
+ return '0.00 seconds (stopped)';
59
+ }
60
+ const totalSeconds = this.duration;
61
+ if (totalSeconds > 60) {
62
+ const minutes = Math.floor(totalSeconds / 60);
63
+ const seconds = totalSeconds % 60.0;
64
+ return `${minutes.toFixed(0)} minute${minutes === 1 ? '' : 's'} ${seconds.toFixed(1)} seconds`;
65
+ }
66
+ else {
67
+ return `${totalSeconds.toFixed(2)} seconds`;
68
+ }
69
+ }
70
+ /**
71
+ * Get the duration in seconds.
72
+ */
73
+ get duration() {
74
+ if (this._startTime === undefined) {
75
+ return 0;
76
+ }
77
+ const curTime = this._endTime !== undefined ? this._endTime : performance.now();
78
+ return (curTime - this._startTime) / 1000.0;
79
+ }
80
+ /**
81
+ * Return the start time of the most recent stopwatch run.
82
+ */
83
+ get startTime() {
84
+ return this._startTime;
85
+ }
86
+ /**
87
+ * Return the end time of the most recent stopwatch run.
88
+ */
89
+ get endTime() {
90
+ return this._endTime;
91
+ }
92
+ }
93
+ //# sourceMappingURL=Stopwatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stopwatch.js","sourceRoot":"","sources":["../src/Stopwatch.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D;;;;;GAKG;AACH,MAAM,OAAO,SAAS;IAKpB;QACE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,KAAK;QACjB,OAAO,IAAI,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,KAAK;QACV,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QACpC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,IAAI;QACT,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9E,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,QAAQ;QACb,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACpD,OAAO,wBAAwB,CAAC;QAClC,CAAC;QACD,MAAM,YAAY,GAAW,IAAI,CAAC,QAAQ,CAAC;QAE3C,IAAI,YAAY,GAAG,EAAE,EAAE,CAAC;YACtB,MAAM,OAAO,GAAW,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;YACtD,MAAM,OAAO,GAAW,YAAY,GAAG,IAAI,CAAC;YAE5C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;QACjG,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;QAC9C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAW,QAAQ;QACjB,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,OAAO,GAAW,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;QAExF,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * Represents a typical timer/stopwatch which keeps track\n * of elapsed time in between two events.\n *\n * @public\n */\nexport class Stopwatch {\n private _startTime: number | undefined;\n private _endTime: number | undefined;\n private _running: boolean;\n\n public constructor() {\n this._startTime = undefined;\n this._endTime = undefined;\n this._running = false;\n }\n\n /**\n * Static helper function which creates a stopwatch which is immediately started\n */\n public static start(): Stopwatch {\n return new Stopwatch().start();\n }\n\n public get isRunning(): boolean {\n return this._running;\n }\n\n /**\n * Starts the stopwatch. Note that if end() has been called,\n * reset() should be called before calling start() again.\n */\n public start(): Stopwatch {\n if (this._startTime !== undefined) {\n throw new Error('Call reset() before starting the Stopwatch');\n }\n this._startTime = performance.now();\n this._endTime = undefined;\n this._running = true;\n return this;\n }\n\n /**\n * Stops executing the stopwatch and saves the current timestamp\n */\n public stop(): Stopwatch {\n this._endTime = this._startTime !== undefined ? performance.now() : undefined;\n this._running = false;\n return this;\n }\n\n /**\n * Resets all values of the stopwatch back to the original\n */\n public reset(): Stopwatch {\n this._endTime = this._startTime = undefined;\n this._running = false;\n return this;\n }\n\n /**\n * Displays how long the stopwatch has been executing in a human readable format.\n */\n public toString(): string {\n if (!this._running && this._startTime === undefined) {\n return '0.00 seconds (stopped)';\n }\n const totalSeconds: number = this.duration;\n\n if (totalSeconds > 60) {\n const minutes: number = Math.floor(totalSeconds / 60);\n const seconds: number = totalSeconds % 60.0;\n\n return `${minutes.toFixed(0)} minute${minutes === 1 ? '' : 's'} ${seconds.toFixed(1)} seconds`;\n } else {\n return `${totalSeconds.toFixed(2)} seconds`;\n }\n }\n\n /**\n * Get the duration in seconds.\n */\n public get duration(): number {\n if (this._startTime === undefined) {\n return 0;\n }\n const curTime: number = this._endTime !== undefined ? this._endTime : performance.now();\n\n return (curTime - this._startTime) / 1000.0;\n }\n\n /**\n * Return the start time of the most recent stopwatch run.\n */\n public get startTime(): number | undefined {\n return this._startTime;\n }\n\n /**\n * Return the end time of the most recent stopwatch run.\n */\n public get endTime(): number | undefined {\n return this._endTime;\n }\n}\n"]}
@@ -0,0 +1,210 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { once } from 'node:events';
4
+ import { AlreadyReportedError } from '@rushstack/node-core-library';
5
+ import { OperationStatus } from './OperationStatus';
6
+ /**
7
+ * This class implements a watch loop.
8
+ *
9
+ * @beta
10
+ */
11
+ export class WatchLoop {
12
+ constructor(options) {
13
+ /**
14
+ * Requests that a new run occur.
15
+ */
16
+ this.requestRun = (requestor, detail) => {
17
+ if (!this._runRequested) {
18
+ this._options.onRequestRun(requestor, detail);
19
+ this._runRequested = true;
20
+ if (this._isRunning) {
21
+ this._options.onAbort();
22
+ this._abortCurrent();
23
+ }
24
+ }
25
+ this._resolveRequestRun([requestor, detail]);
26
+ };
27
+ /**
28
+ * Cancels the current iteration (if possible).
29
+ */
30
+ this._abortCurrent = () => {
31
+ this._abortController.abort();
32
+ };
33
+ this._options = options;
34
+ this._abortController = new AbortController();
35
+ this._isRunning = false;
36
+ // Always start as true, so that any requests prior to first run are silenced.
37
+ this._runRequested = true;
38
+ this._requestRunPromise = new Promise((resolve) => {
39
+ this._resolveRequestRun = resolve;
40
+ });
41
+ }
42
+ /**
43
+ * Runs the inner loop until the abort signal is cancelled or a run completes without a new run being requested.
44
+ */
45
+ async runUntilStableAsync(abortSignal) {
46
+ if (abortSignal.aborted) {
47
+ return OperationStatus.Aborted;
48
+ }
49
+ abortSignal.addEventListener('abort', this._abortCurrent, { once: true });
50
+ try {
51
+ let result = OperationStatus.Ready;
52
+ do {
53
+ // Always check the abort signal first, in case it was aborted in the async tick since the last executeAsync() call.
54
+ if (abortSignal.aborted) {
55
+ return OperationStatus.Aborted;
56
+ }
57
+ result = await this._runIterationAsync();
58
+ } while (this._runRequested);
59
+ // Even if the run has finished, if the abort signal was aborted, we should return `Aborted` just in case.
60
+ return abortSignal.aborted ? OperationStatus.Aborted : result;
61
+ }
62
+ finally {
63
+ abortSignal.removeEventListener('abort', this._abortCurrent);
64
+ }
65
+ }
66
+ /**
67
+ * Runs the inner loop until the abort signal is aborted. Will otherwise wait indefinitely for a new run to be requested.
68
+ */
69
+ async runUntilAbortedAsync(abortSignal, onWaiting) {
70
+ if (abortSignal.aborted) {
71
+ return;
72
+ }
73
+ const abortPromise = once(abortSignal, 'abort');
74
+ while (!abortSignal.aborted) {
75
+ await this.runUntilStableAsync(abortSignal);
76
+ onWaiting();
77
+ await Promise.race([this._requestRunPromise, abortPromise]);
78
+ }
79
+ }
80
+ /**
81
+ * Sets up an IPC handler that will run the inner loop when it receives a "run" message from the host.
82
+ * Runs until receiving an "exit" message from the host, or aborts early if an unhandled error is thrown.
83
+ */
84
+ async runIPCAsync(host = process) {
85
+ await new Promise((resolve, reject) => {
86
+ let abortController = new AbortController();
87
+ let runRequestedFromHost = true;
88
+ let status = OperationStatus.Ready;
89
+ function tryMessageHost(message) {
90
+ if (!host.send) {
91
+ return reject(new Error('Host does not support IPC'));
92
+ }
93
+ try {
94
+ host.send(message);
95
+ }
96
+ catch (err) {
97
+ reject(new Error(`Unable to communicate with host: ${err}`));
98
+ }
99
+ }
100
+ function requestRunFromHost(requestor, detail) {
101
+ if (runRequestedFromHost) {
102
+ return;
103
+ }
104
+ runRequestedFromHost = true;
105
+ const requestRunMessage = {
106
+ event: 'requestRun',
107
+ requestor,
108
+ detail
109
+ };
110
+ tryMessageHost(requestRunMessage);
111
+ }
112
+ function sendSync() {
113
+ const syncMessage = {
114
+ event: 'sync',
115
+ status
116
+ };
117
+ tryMessageHost(syncMessage);
118
+ }
119
+ host.on('message', async (message) => {
120
+ switch (message.command) {
121
+ case 'exit': {
122
+ return resolve();
123
+ }
124
+ case 'cancel': {
125
+ if (this._isRunning) {
126
+ abortController.abort();
127
+ abortController = new AbortController();
128
+ // This will terminate the currently executing `runUntilStableAsync` call.
129
+ }
130
+ return;
131
+ }
132
+ case 'run': {
133
+ runRequestedFromHost = false;
134
+ status = OperationStatus.Executing;
135
+ try {
136
+ status = await this.runUntilStableAsync(abortController.signal);
137
+ // ESLINT: "Promises must be awaited, end with a call to .catch, end with a call to .then ..."
138
+ this._requestRunPromise.then(([requestor, detail]) => requestRunFromHost(requestor, detail), (error) => {
139
+ // Unreachable code. The promise will never be rejected.
140
+ });
141
+ }
142
+ catch (err) {
143
+ status = OperationStatus.Failure;
144
+ return reject(err);
145
+ }
146
+ finally {
147
+ const afterExecuteMessage = {
148
+ event: 'after-execute',
149
+ status
150
+ };
151
+ tryMessageHost(afterExecuteMessage);
152
+ }
153
+ return;
154
+ }
155
+ case 'sync': {
156
+ return sendSync();
157
+ }
158
+ default: {
159
+ return reject(new Error(`Unexpected command from host: ${message}`));
160
+ }
161
+ }
162
+ });
163
+ sendSync();
164
+ });
165
+ }
166
+ /**
167
+ * The abort signal for the current iteration.
168
+ */
169
+ get abortSignal() {
170
+ return this._abortController.signal;
171
+ }
172
+ /**
173
+ * Resets the abort signal and run request state.
174
+ */
175
+ _reset() {
176
+ if (this._abortController.signal.aborted) {
177
+ this._abortController = new AbortController();
178
+ }
179
+ if (this._runRequested) {
180
+ this._runRequested = false;
181
+ this._requestRunPromise = new Promise((resolve) => {
182
+ this._resolveRequestRun = resolve;
183
+ });
184
+ }
185
+ }
186
+ /**
187
+ * Runs a single iteration of the loop.
188
+ * @returns The status of the iteration.
189
+ */
190
+ async _runIterationAsync() {
191
+ this._reset();
192
+ this._options.onBeforeExecute();
193
+ try {
194
+ this._isRunning = true;
195
+ return await this._options.executeAsync(this);
196
+ }
197
+ catch (err) {
198
+ if (!(err instanceof AlreadyReportedError)) {
199
+ throw err;
200
+ }
201
+ else {
202
+ return OperationStatus.Failure;
203
+ }
204
+ }
205
+ finally {
206
+ this._isRunning = false;
207
+ }
208
+ }
209
+ }
210
+ //# sourceMappingURL=WatchLoop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WatchLoop.js","sourceRoot":"","sources":["../src/WatchLoop.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { once } from 'node:events';\n\nimport { AlreadyReportedError } from '@rushstack/node-core-library';\n\nimport type { OperationRequestRunCallback } from './Operation';\nimport { OperationStatus } from './OperationStatus';\nimport type {\n IAfterExecuteEventMessage,\n IPCHost,\n CommandMessageFromHost,\n ISyncEventMessage,\n IRequestRunEventMessage\n} from './protocol.types';\n\n/**\n * Callbacks for the watch loop.\n *\n * @beta\n */\nexport interface IWatchLoopOptions {\n /**\n * Callback that performs the core work of a single iteration.\n */\n executeAsync: (state: IWatchLoopState) => Promise<OperationStatus>;\n /**\n * Logging callback immediately before execution occurs.\n */\n onBeforeExecute: () => void;\n /**\n * Logging callback when a run is requested (and hasn't already been).\n *\n * @param requestor - The name of the operation requesting a rerun.\n * @param detail - Optional detail about why the rerun is requested, e.g. the name of a changed file.\n */\n onRequestRun: OperationRequestRunCallback;\n /**\n * Logging callback when a run is aborted.\n */\n onAbort: () => void;\n}\n\n/**\n * The public API surface of the watch loop, for use in the `executeAsync` callback.\n *\n * @beta\n */\nexport interface IWatchLoopState {\n get abortSignal(): AbortSignal;\n requestRun: OperationRequestRunCallback;\n}\n\n/**\n * This class implements a watch loop.\n *\n * @beta\n */\nexport class WatchLoop implements IWatchLoopState {\n private readonly _options: Readonly<IWatchLoopOptions>;\n\n private _abortController: AbortController;\n private _isRunning: boolean;\n private _runRequested: boolean;\n private _requestRunPromise: Promise<[string, string?]>;\n private _resolveRequestRun!: (value: [string, string?]) => void;\n\n public constructor(options: IWatchLoopOptions) {\n this._options = options;\n\n this._abortController = new AbortController();\n this._isRunning = false;\n // Always start as true, so that any requests prior to first run are silenced.\n this._runRequested = true;\n this._requestRunPromise = new Promise<[string, string?]>((resolve) => {\n this._resolveRequestRun = resolve;\n });\n }\n\n /**\n * Runs the inner loop until the abort signal is cancelled or a run completes without a new run being requested.\n */\n public async runUntilStableAsync(abortSignal: AbortSignal): Promise<OperationStatus> {\n if (abortSignal.aborted) {\n return OperationStatus.Aborted;\n }\n\n abortSignal.addEventListener('abort', this._abortCurrent, { once: true });\n\n try {\n let result: OperationStatus = OperationStatus.Ready;\n\n do {\n // Always check the abort signal first, in case it was aborted in the async tick since the last executeAsync() call.\n if (abortSignal.aborted) {\n return OperationStatus.Aborted;\n }\n\n result = await this._runIterationAsync();\n } while (this._runRequested);\n\n // Even if the run has finished, if the abort signal was aborted, we should return `Aborted` just in case.\n return abortSignal.aborted ? OperationStatus.Aborted : result;\n } finally {\n abortSignal.removeEventListener('abort', this._abortCurrent);\n }\n }\n\n /**\n * Runs the inner loop until the abort signal is aborted. Will otherwise wait indefinitely for a new run to be requested.\n */\n public async runUntilAbortedAsync(abortSignal: AbortSignal, onWaiting: () => void): Promise<void> {\n if (abortSignal.aborted) {\n return;\n }\n\n const abortPromise: Promise<unknown> = once(abortSignal, 'abort');\n\n while (!abortSignal.aborted) {\n await this.runUntilStableAsync(abortSignal);\n\n onWaiting();\n await Promise.race([this._requestRunPromise, abortPromise]);\n }\n }\n\n /**\n * Sets up an IPC handler that will run the inner loop when it receives a \"run\" message from the host.\n * Runs until receiving an \"exit\" message from the host, or aborts early if an unhandled error is thrown.\n */\n public async runIPCAsync(host: IPCHost = process): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let abortController: AbortController = new AbortController();\n\n let runRequestedFromHost: boolean = true;\n let status: OperationStatus = OperationStatus.Ready;\n\n function tryMessageHost(\n message: ISyncEventMessage | IRequestRunEventMessage | IAfterExecuteEventMessage\n ): void {\n if (!host.send) {\n return reject(new Error('Host does not support IPC'));\n }\n\n try {\n host.send(message);\n } catch (err) {\n reject(new Error(`Unable to communicate with host: ${err}`));\n }\n }\n\n function requestRunFromHost(requestor: string, detail?: string): void {\n if (runRequestedFromHost) {\n return;\n }\n\n runRequestedFromHost = true;\n\n const requestRunMessage: IRequestRunEventMessage = {\n event: 'requestRun',\n requestor,\n detail\n };\n\n tryMessageHost(requestRunMessage);\n }\n\n function sendSync(): void {\n const syncMessage: ISyncEventMessage = {\n event: 'sync',\n status\n };\n tryMessageHost(syncMessage);\n }\n\n host.on('message', async (message: CommandMessageFromHost) => {\n switch (message.command) {\n case 'exit': {\n return resolve();\n }\n\n case 'cancel': {\n if (this._isRunning) {\n abortController.abort();\n abortController = new AbortController();\n // This will terminate the currently executing `runUntilStableAsync` call.\n }\n return;\n }\n\n case 'run': {\n runRequestedFromHost = false;\n\n status = OperationStatus.Executing;\n\n try {\n status = await this.runUntilStableAsync(abortController.signal);\n // ESLINT: \"Promises must be awaited, end with a call to .catch, end with a call to .then ...\"\n this._requestRunPromise.then(\n ([requestor, detail]) => requestRunFromHost(requestor, detail),\n (error: Error) => {\n // Unreachable code. The promise will never be rejected.\n }\n );\n } catch (err) {\n status = OperationStatus.Failure;\n return reject(err);\n } finally {\n const afterExecuteMessage: IAfterExecuteEventMessage = {\n event: 'after-execute',\n status\n };\n tryMessageHost(afterExecuteMessage);\n }\n return;\n }\n\n case 'sync': {\n return sendSync();\n }\n\n default: {\n return reject(new Error(`Unexpected command from host: ${message}`));\n }\n }\n });\n\n sendSync();\n });\n }\n\n /**\n * Requests that a new run occur.\n */\n public requestRun: OperationRequestRunCallback = (requestor: string, detail?: string) => {\n if (!this._runRequested) {\n this._options.onRequestRun(requestor, detail);\n this._runRequested = true;\n if (this._isRunning) {\n this._options.onAbort();\n this._abortCurrent();\n }\n }\n this._resolveRequestRun([requestor, detail]);\n };\n\n /**\n * The abort signal for the current iteration.\n */\n public get abortSignal(): AbortSignal {\n return this._abortController.signal;\n }\n\n /**\n * Cancels the current iteration (if possible).\n */\n private _abortCurrent = (): void => {\n this._abortController.abort();\n };\n\n /**\n * Resets the abort signal and run request state.\n */\n private _reset(): void {\n if (this._abortController.signal.aborted) {\n this._abortController = new AbortController();\n }\n\n if (this._runRequested) {\n this._runRequested = false;\n this._requestRunPromise = new Promise<[string, string?]>((resolve) => {\n this._resolveRequestRun = resolve;\n });\n }\n }\n\n /**\n * Runs a single iteration of the loop.\n * @returns The status of the iteration.\n */\n private async _runIterationAsync(): Promise<OperationStatus> {\n this._reset();\n\n this._options.onBeforeExecute();\n try {\n this._isRunning = true;\n return await this._options.executeAsync(this);\n } catch (err) {\n if (!(err instanceof AlreadyReportedError)) {\n throw err;\n } else {\n return OperationStatus.Failure;\n }\n } finally {\n this._isRunning = false;\n }\n }\n}\n"]}
@@ -0,0 +1,49 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { Async, MinimumHeap } from '@rushstack/node-core-library';
4
+ import { OperationStatus } from './OperationStatus';
5
+ export class WorkQueue {
6
+ constructor(abortSignal) {
7
+ // Sort by priority descending. Thus the comparator returns a negative number if a has higher priority than b.
8
+ this._queue = new MinimumHeap((a, b) => b.priority - a.priority);
9
+ this._abortSignal = abortSignal;
10
+ this._abortPromise = abortSignal.aborted
11
+ ? Promise.resolve()
12
+ : new Promise((resolve) => {
13
+ abortSignal.addEventListener('abort', () => resolve(), { once: true });
14
+ });
15
+ [this._pushPromise, this._resolvePush] = Async.getSignal();
16
+ this._resolvePushTimeout = undefined;
17
+ }
18
+ async *[Symbol.asyncIterator]() {
19
+ while (!this._abortSignal.aborted) {
20
+ while (this._queue.size > 0) {
21
+ const item = this._queue.poll();
22
+ yield item.task;
23
+ }
24
+ await Promise.race([this._pushPromise, this._abortPromise]);
25
+ }
26
+ }
27
+ pushAsync(task, priority) {
28
+ return new Promise((resolve, reject) => {
29
+ this._queue.push({
30
+ task: () => task().then(resolve, reject),
31
+ priority
32
+ });
33
+ // ESLINT: "Promises must be awaited, end with a call to .catch, end with a call to .then ..."
34
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
35
+ this._abortPromise.finally(() => resolve(OperationStatus.Aborted));
36
+ this._resolvePushDebounced();
37
+ });
38
+ }
39
+ _resolvePushDebounced() {
40
+ if (!this._resolvePushTimeout) {
41
+ this._resolvePushTimeout = setTimeout(() => {
42
+ this._resolvePushTimeout = undefined;
43
+ this._resolvePush();
44
+ [this._pushPromise, this._resolvePush] = Async.getSignal();
45
+ });
46
+ }
47
+ }
48
+ }
49
+ //# sourceMappingURL=WorkQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkQueue.js","sourceRoot":"","sources":["../src/WorkQueue.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAOpD,MAAM,OAAO,SAAS;IASpB,YAAmB,WAAwB;QACzC,8GAA8G;QAC9G,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,CAAC,CAAa,EAAE,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzF,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,OAAO;YACtC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE;YACnB,CAAC,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAC5B,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC;QAEP,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QAC3D,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;IACvC,CAAC;IAEM,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAe,IAAI,CAAC,MAAM,CAAC,IAAI,EAAG,CAAC;gBAC7C,MAAM,IAAI,CAAC,IAAI,CAAC;YAClB,CAAC;YAED,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAEM,SAAS,CAAC,IAAoC,EAAE,QAAgB;QACrE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;gBACxC,QAAQ;aACT,CAAC,CAAC;YAEH,8FAA8F;YAC9F,mEAAmE;YACnE,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;YAEnE,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,qBAAqB;QAC3B,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9B,IAAI,CAAC,mBAAmB,GAAG,UAAU,CAAC,GAAG,EAAE;gBACzC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;gBACrC,IAAI,CAAC,YAAY,EAAE,CAAC;gBAEpB,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YAC7D,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { Async, MinimumHeap } from '@rushstack/node-core-library';\n\nimport { OperationStatus } from './OperationStatus';\n\ninterface IQueueItem {\n task: () => Promise<void>;\n priority: number;\n}\n\nexport class WorkQueue {\n private readonly _queue: MinimumHeap<IQueueItem>;\n private readonly _abortSignal: AbortSignal;\n private readonly _abortPromise: Promise<void>;\n\n private _pushPromise: Promise<void>;\n private _resolvePush: () => void;\n private _resolvePushTimeout: NodeJS.Timeout | undefined;\n\n public constructor(abortSignal: AbortSignal) {\n // Sort by priority descending. Thus the comparator returns a negative number if a has higher priority than b.\n this._queue = new MinimumHeap((a: IQueueItem, b: IQueueItem) => b.priority - a.priority);\n this._abortSignal = abortSignal;\n this._abortPromise = abortSignal.aborted\n ? Promise.resolve()\n : new Promise<void>((resolve) => {\n abortSignal.addEventListener('abort', () => resolve(), { once: true });\n });\n\n [this._pushPromise, this._resolvePush] = Async.getSignal();\n this._resolvePushTimeout = undefined;\n }\n\n public async *[Symbol.asyncIterator](): AsyncIterableIterator<() => Promise<void>> {\n while (!this._abortSignal.aborted) {\n while (this._queue.size > 0) {\n const item: IQueueItem = this._queue.poll()!;\n yield item.task;\n }\n\n await Promise.race([this._pushPromise, this._abortPromise]);\n }\n }\n\n public pushAsync(task: () => Promise<OperationStatus>, priority: number): Promise<OperationStatus> {\n return new Promise((resolve, reject) => {\n this._queue.push({\n task: () => task().then(resolve, reject),\n priority\n });\n\n // ESLINT: \"Promises must be awaited, end with a call to .catch, end with a call to .then ...\"\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this._abortPromise.finally(() => resolve(OperationStatus.Aborted));\n\n this._resolvePushDebounced();\n });\n }\n\n private _resolvePushDebounced(): void {\n if (!this._resolvePushTimeout) {\n this._resolvePushTimeout = setTimeout(() => {\n this._resolvePushTimeout = undefined;\n this._resolvePush();\n\n [this._pushPromise, this._resolvePush] = Async.getSignal();\n });\n }\n }\n}\n"]}
@@ -0,0 +1,83 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ /**
4
+ * For every operation in the input, computes the length of the longest chain of operations that depend on it.
5
+ * This value is stored as `operation.criticalPathLength`.
6
+ */
7
+ export function calculateCriticalPathLengths(operations) {
8
+ // Clone the set of operations as an array, so that we can sort it.
9
+ const queue = Array.from(operations);
10
+ // Create a collection for detecting visited nodes
11
+ const cycleDetectorStack = new Set();
12
+ for (const operation of queue) {
13
+ calculateCriticalPathLength(operation, cycleDetectorStack);
14
+ }
15
+ return queue;
16
+ }
17
+ /**
18
+ * Calculates the shortest path from `startOperation` to `endOperation`.
19
+ * Used when printing out circular dependencies.
20
+ */
21
+ export function calculateShortestPath(startOperation, endOperation) {
22
+ // Map of each operation to the most optimal parent
23
+ const parents = new Map([[endOperation, undefined]]);
24
+ let finalParent;
25
+ // Run a breadth-first search to find the shortest path between the start and end operations
26
+ outer: for (const [operation] of parents) {
27
+ for (const consumer of operation.consumers) {
28
+ // Since this is a breadth-first traversal, the first encountered path to a given node
29
+ // will be tied for shortest, so only the first encountered path needs to be tracked
30
+ if (!parents.has(consumer)) {
31
+ parents.set(consumer, operation);
32
+ }
33
+ if (consumer === startOperation) {
34
+ finalParent = operation;
35
+ break outer;
36
+ }
37
+ }
38
+ }
39
+ if (!finalParent) {
40
+ throw new Error(`Could not find a path from "${startOperation.name}" to "${endOperation.name}"`);
41
+ }
42
+ // Walk back up the path from the end operation to the start operation
43
+ let currentOperation = finalParent;
44
+ const path = [startOperation];
45
+ while (currentOperation !== undefined) {
46
+ path.push(currentOperation);
47
+ currentOperation = parents.get(currentOperation);
48
+ }
49
+ return path;
50
+ }
51
+ /**
52
+ * Perform a depth-first search to find critical path length to the provided operation.
53
+ * Cycle detection comes at minimal additional cost.
54
+ */
55
+ export function calculateCriticalPathLength(operation, dependencyChain) {
56
+ if (dependencyChain.has(operation)) {
57
+ // Ensure we have the shortest path to the cycle
58
+ const shortestPath = calculateShortestPath(operation, operation);
59
+ throw new Error('A cyclic dependency was encountered:\n ' +
60
+ shortestPath.map((visitedTask) => visitedTask.name).join('\n -> '));
61
+ }
62
+ let { criticalPathLength } = operation;
63
+ if (criticalPathLength !== undefined) {
64
+ // This has been visited already
65
+ return criticalPathLength;
66
+ }
67
+ criticalPathLength = 0;
68
+ if (operation.consumers.size) {
69
+ dependencyChain.add(operation);
70
+ for (const consumer of operation.consumers) {
71
+ criticalPathLength = Math.max(criticalPathLength, calculateCriticalPathLength(consumer, dependencyChain));
72
+ }
73
+ dependencyChain.delete(operation);
74
+ }
75
+ // Include the contribution from the current operation
76
+ criticalPathLength += operation.weight ?? 1;
77
+ // Record result
78
+ operation.criticalPathLength = criticalPathLength;
79
+ // Directly writing operations to an output collection here would yield a topological sorted set
80
+ // However, we want a bit more fine-tuning of the output than just the raw topology
81
+ return criticalPathLength;
82
+ }
83
+ //# sourceMappingURL=calculateCriticalPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculateCriticalPath.js","sourceRoot":"","sources":["../src/calculateCriticalPath.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport interface ISortableOperation<T extends ISortableOperation<T>> {\n name: string | undefined;\n criticalPathLength?: number | undefined;\n weight: number;\n consumers: Set<T>;\n}\n\n/**\n * For every operation in the input, computes the length of the longest chain of operations that depend on it.\n * This value is stored as `operation.criticalPathLength`.\n */\nexport function calculateCriticalPathLengths<T extends ISortableOperation<T>>(operations: Iterable<T>): T[] {\n // Clone the set of operations as an array, so that we can sort it.\n const queue: T[] = Array.from(operations);\n\n // Create a collection for detecting visited nodes\n const cycleDetectorStack: Set<T> = new Set();\n for (const operation of queue) {\n calculateCriticalPathLength(operation, cycleDetectorStack);\n }\n\n return queue;\n}\n\n/**\n * Calculates the shortest path from `startOperation` to `endOperation`.\n * Used when printing out circular dependencies.\n */\nexport function calculateShortestPath<T extends ISortableOperation<T>>(\n startOperation: T,\n endOperation: T\n): T[] {\n // Map of each operation to the most optimal parent\n const parents: Map<T, T | undefined> = new Map([[endOperation, undefined]]);\n let finalParent: T | undefined;\n\n // Run a breadth-first search to find the shortest path between the start and end operations\n outer: for (const [operation] of parents) {\n for (const consumer of operation.consumers) {\n // Since this is a breadth-first traversal, the first encountered path to a given node\n // will be tied for shortest, so only the first encountered path needs to be tracked\n if (!parents.has(consumer)) {\n parents.set(consumer, operation);\n }\n\n if (consumer === startOperation) {\n finalParent = operation;\n break outer;\n }\n }\n }\n\n if (!finalParent) {\n throw new Error(`Could not find a path from \"${startOperation.name}\" to \"${endOperation.name}\"`);\n }\n\n // Walk back up the path from the end operation to the start operation\n let currentOperation: T = finalParent;\n const path: T[] = [startOperation];\n while (currentOperation !== undefined) {\n path.push(currentOperation);\n currentOperation = parents.get(currentOperation)!;\n }\n return path;\n}\n\n/**\n * Perform a depth-first search to find critical path length to the provided operation.\n * Cycle detection comes at minimal additional cost.\n */\nexport function calculateCriticalPathLength<T extends ISortableOperation<T>>(\n operation: T,\n dependencyChain: Set<T>\n): number {\n if (dependencyChain.has(operation)) {\n // Ensure we have the shortest path to the cycle\n const shortestPath: T[] = calculateShortestPath(operation, operation);\n\n throw new Error(\n 'A cyclic dependency was encountered:\\n ' +\n shortestPath.map((visitedTask) => visitedTask.name).join('\\n -> ')\n );\n }\n\n let { criticalPathLength } = operation;\n\n if (criticalPathLength !== undefined) {\n // This has been visited already\n return criticalPathLength;\n }\n\n criticalPathLength = 0;\n if (operation.consumers.size) {\n dependencyChain.add(operation);\n for (const consumer of operation.consumers) {\n criticalPathLength = Math.max(\n criticalPathLength,\n calculateCriticalPathLength(consumer, dependencyChain)\n );\n }\n dependencyChain.delete(operation);\n }\n // Include the contribution from the current operation\n criticalPathLength += operation.weight ?? 1;\n\n // Record result\n operation.criticalPathLength = criticalPathLength;\n\n // Directly writing operations to an output collection here would yield a topological sorted set\n // However, we want a bit more fine-tuning of the output than just the raw topology\n\n return criticalPathLength;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ export { Operation } from './Operation';
4
+ export { OperationError } from './OperationError';
5
+ export { OperationExecutionManager } from './OperationExecutionManager';
6
+ export { OperationGroupRecord } from './OperationGroupRecord';
7
+ export { OperationStatus } from './OperationStatus';
8
+ export { Stopwatch } from './Stopwatch';
9
+ export { WatchLoop } from './WatchLoop';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAwB3D,OAAO,EAGL,SAAS,EAEV,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAmC,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAEzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAgD,SAAS,EAAE,MAAM,aAAa,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/// <reference types=\"node\" preserve=\"true\" />\n\nexport type {\n IOperationRunner,\n IOperationRunnerContext,\n IOperationState,\n IOperationStates\n} from './IOperationRunner';\n\nexport type {\n IAfterExecuteEventMessage,\n ISyncEventMessage,\n IRequestRunEventMessage,\n EventMessageFromClient,\n ICancelCommandMessage,\n IExitCommandMessage,\n IRunCommandMessage,\n ISyncCommandMessage,\n CommandMessageFromHost,\n IPCHost\n} from './protocol.types';\n\nexport {\n type IExecuteOperationContext,\n type IOperationOptions,\n Operation,\n type OperationRequestRunCallback\n} from './Operation';\n\nexport { OperationError } from './OperationError';\n\nexport { type IOperationExecutionOptions, OperationExecutionManager } from './OperationExecutionManager';\n\nexport { OperationGroupRecord } from './OperationGroupRecord';\n\nexport { OperationStatus } from './OperationStatus';\n\nexport { Stopwatch } from './Stopwatch';\n\nexport { type IWatchLoopOptions, type IWatchLoopState, WatchLoop } from './WatchLoop';\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ export {};
4
+ //# sourceMappingURL=protocol.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.types.js","sourceRoot":"","sources":["../src/protocol.types.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { OperationStatus } from './OperationStatus';\n\n/**\n * A message sent to the host to ask it to run this task.\n *\n * @beta\n */\nexport interface IRequestRunEventMessage {\n event: 'requestRun';\n /**\n * The name of the operation requesting a rerun.\n */\n requestor: string;\n /**\n * Optional detail about why the rerun is requested, e.g. the name of a changed file.\n */\n detail?: string;\n}\n\n/**\n * A message sent to the host upon completion of a run of this task.\n *\n * @beta\n */\nexport interface IAfterExecuteEventMessage {\n event: 'after-execute';\n status: OperationStatus;\n}\n\n/**\n * A message sent to the host upon connection of the channel, to indicate\n * to the host that this task supports the protocol and to provide baseline status information.\n *\n * @beta\n */\nexport interface ISyncEventMessage {\n event: 'sync';\n status: OperationStatus;\n}\n\n/**\n * A message sent by the host to tell the watch loop to cancel the current run.\n *\n * @beta\n */\nexport interface ICancelCommandMessage {\n command: 'cancel';\n}\n\n/**\n * A message sent by the host to tell the watch loop to shutdown gracefully.\n *\n * @beta\n */\nexport interface IExitCommandMessage {\n command: 'exit';\n}\n\n/**\n * A message sent by the host to tell the watch loop to perform a single run.\n *\n * @beta\n */\nexport interface IRunCommandMessage {\n command: 'run';\n}\n\n/**\n * A message sent by the host to ask for to resync status information.\n *\n * @beta\n */\nexport interface ISyncCommandMessage {\n command: 'sync';\n}\n\n/**\n * The set of known messages from the host to the watch loop.\n * @beta\n */\nexport type CommandMessageFromHost =\n | ICancelCommandMessage\n | IExitCommandMessage\n | IRunCommandMessage\n | ISyncCommandMessage;\n\n/**\n * The set of known messages from the watch loop to the host.\n * @beta\n */\nexport type EventMessageFromClient = IRequestRunEventMessage | IAfterExecuteEventMessage | ISyncEventMessage;\n\n/**\n * The interface contract for IPC send/receive, to support alternate channels and unit tests.\n *\n * @beta\n */\nexport type IPCHost = Pick<typeof process, 'on' | 'send'>;\n"]}
package/package.json CHANGED
@@ -1,9 +1,32 @@
1
1
  {
2
2
  "name": "@rushstack/operation-graph",
3
- "version": "0.5.7",
3
+ "version": "0.6.1",
4
4
  "description": "Library for managing and executing operations in a directed acyclic graph.",
5
- "main": "lib/index.js",
6
- "typings": "dist/operation-graph.d.ts",
5
+ "main": "./lib-commonjs/index.js",
6
+ "module": "./lib-esm/index.js",
7
+ "types": "./dist/operation-graph.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/operation-graph.d.ts",
11
+ "node": "./lib-commonjs/index.js",
12
+ "import": "./lib-esm/index.js",
13
+ "require": "./lib-commonjs/index.js"
14
+ },
15
+ "./lib/*": {
16
+ "types": "./lib-dts/*.d.ts",
17
+ "node": "./lib-commonjs/*.js",
18
+ "import": "./lib-esm/*.js",
19
+ "require": "./lib-commonjs/*.js"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "typesVersions": {
24
+ "*": {
25
+ "lib/*": [
26
+ "lib-dts/*"
27
+ ]
28
+ }
29
+ },
7
30
  "license": "MIT",
8
31
  "repository": {
9
32
  "url": "https://github.com/microsoft/rushstack.git",
@@ -11,11 +34,11 @@
11
34
  "directory": "libraries/operation-graph"
12
35
  },
13
36
  "dependencies": {
14
- "@rushstack/node-core-library": "5.19.1",
15
- "@rushstack/terminal": "0.21.0"
37
+ "@rushstack/node-core-library": "5.20.1",
38
+ "@rushstack/terminal": "0.22.1"
16
39
  },
17
40
  "devDependencies": {
18
- "@rushstack/heft": "1.1.7",
41
+ "@rushstack/heft": "1.2.0",
19
42
  "eslint": "~9.37.0",
20
43
  "decoupled-local-node-rig": "1.0.0"
21
44
  },
@@ -27,6 +50,7 @@
27
50
  "optional": true
28
51
  }
29
52
  },
53
+ "sideEffects": false,
30
54
  "scripts": {
31
55
  "build": "heft build --clean",
32
56
  "_phase:build": "heft run --only build -- --clean",
File without changes
File without changes