@rushstack/operation-graph 0.6.3 → 0.6.5
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.
- package/CHANGELOG.json +30 -0
- package/CHANGELOG.md +11 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib-commonjs/Operation.js +6 -5
- package/lib-commonjs/Operation.js.map +1 -1
- package/lib-dts/Operation.d.ts.map +1 -1
- package/lib-esm/Operation.js +6 -5
- package/lib-esm/Operation.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.json
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rushstack/operation-graph",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.6.5",
|
|
6
|
+
"tag": "@rushstack/operation-graph_v0.6.5",
|
|
7
|
+
"date": "Thu, 09 Apr 2026 00:15:07 GMT",
|
|
8
|
+
"comments": {
|
|
9
|
+
"dependency": [
|
|
10
|
+
{
|
|
11
|
+
"comment": "Updating dependency \"@rushstack/node-core-library\" to `5.22.0`"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"comment": "Updating dependency \"@rushstack/terminal\" to `0.22.5`"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"version": "0.6.4",
|
|
21
|
+
"tag": "@rushstack/operation-graph_v0.6.4",
|
|
22
|
+
"date": "Tue, 31 Mar 2026 15:14:14 GMT",
|
|
23
|
+
"comments": {
|
|
24
|
+
"dependency": [
|
|
25
|
+
{
|
|
26
|
+
"comment": "Updating dependency \"@rushstack/node-core-library\" to `5.21.0`"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"comment": "Updating dependency \"@rushstack/terminal\" to `0.22.4`"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
4
34
|
{
|
|
5
35
|
"version": "0.6.3",
|
|
6
36
|
"tag": "@rushstack/operation-graph_v0.6.3",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# Change Log - @rushstack/operation-graph
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Thu, 09 Apr 2026 00:15:07 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 0.6.5
|
|
6
|
+
Thu, 09 Apr 2026 00:15:07 GMT
|
|
7
|
+
|
|
8
|
+
_Version update only_
|
|
9
|
+
|
|
10
|
+
## 0.6.4
|
|
11
|
+
Tue, 31 Mar 2026 15:14:14 GMT
|
|
12
|
+
|
|
13
|
+
_Version update only_
|
|
4
14
|
|
|
5
15
|
## 0.6.3
|
|
6
16
|
Wed, 25 Feb 2026 00:34:30 GMT
|
package/dist/tsdoc-metadata.json
CHANGED
|
@@ -77,11 +77,12 @@ class Operation {
|
|
|
77
77
|
* This is used to track state from the `requestRun` callback passed to the runner.
|
|
78
78
|
*/
|
|
79
79
|
this._runPending = true;
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
80
|
+
const { group, runner, weight = 1, name, metadata = {} } = options;
|
|
81
|
+
this.group = group;
|
|
82
|
+
this.runner = runner;
|
|
83
|
+
this.weight = weight;
|
|
84
|
+
this.name = name;
|
|
85
|
+
this.metadata = metadata;
|
|
85
86
|
if (this.group) {
|
|
86
87
|
this.group.addOperation(this);
|
|
87
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Operation.js","sourceRoot":"","sources":["../src/Operation.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAA6D;AAG7D,2CAAwC;AAQxC,uDAAoD;AA+EpD;;;;;;;;GAQG;AACH,MAAa,SAAS;IAiGpB,YAAmB,OAAqD;QA9FxE;;WAEG;QACa,iBAAY,GAA8C,IAAI,GAAG,EAE9E,CAAC;QACJ;;WAEG;QACa,cAAS,GAA8C,IAAI,GAAG,EAE3E,CAAC;QAUJ;;;WAGG;QACI,WAAM,GAAiC,SAAS,CAAC;QAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BG;QACI,uBAAkB,GAAuB,SAAS,CAAC;QAe1D;;WAEG;QACI,cAAS,GAAgC,SAAS,CAAC;QAE1D;;WAEG;QACI,UAAK,GAAgC,SAAS,CAAC;QAEtD;;WAEG;QACK,aAAQ,GAAyC,SAAS,CAAC;QAEnE;;;WAGG;QACK,gBAAW,GAAY,IAAI,CAAC;QAKlC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAK,EAAgB,CAAC;QAEtD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAEM,aAAa,CAAC,UAAgD;QACnE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAEM,gBAAgB,CAAC,UAAgD;QACtE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEM,KAAK;QACV,wBAAwB;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;QAE5B,IAAI,CAAC,KAAK,GAAG;YACX,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,iCAAe,CAAC,OAAO,CAAC,CAAC,CAAC,iCAAe,CAAC,KAAK;YACpF,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,IAAI,KAAK;YAC/C,KAAK,EAAE,SAAS;YAChB,SAAS,EAAE,IAAI,qBAAS,EAAE;SAC3B,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,aAAa,CAAC,OAAiC;QAC1D,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC9B,OAAiC,EACjC,QAAyB;QAEzB,MAAM,KAAK,GAAoB,QAAQ,CAAC;QACxC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAExB,MAAM,iBAAiB,GAA4C,MAAM,OAAO,CAAC,UAAU,CACzF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,UAAqB,EAAE,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAC5F,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;QAEvD,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACxB,KAAK,CAAC,MAAM,GAAG,iCAAe,CAAC,OAAO,CAAC;YACvC,OAAO,KAAK,CAAC,MAAM,CAAC;QACtB,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;YACvC,IACE,MAAM,CAAC,MAAM,KAAK,UAAU;gBAC5B,MAAM,CAAC,KAAK,KAAK,iCAAe,CAAC,OAAO;gBACxC,MAAM,CAAC,KAAK,KAAK,iCAAe,CAAC,OAAO,EACxC,CAAC;gBACD,KAAK,CAAC,MAAM,GAAG,iCAAe,CAAC,OAAO,CAAC;gBACvC,OAAO,KAAK,CAAC,MAAM,CAAC;YACtB,CAAC;QACH,CAAC;QAED,KAAK,CAAC,MAAM,GAAG,iCAAe,CAAC,KAAK,CAAC;QAErC,MAAM,YAAY,GAA4B;YAC5C,WAAW;YACX,UAAU,EAAE,CAAC,KAAK,CAAC,UAAU;YAC7B,UAAU,EAAE,UAAU;gBACpB,CAAC,CAAC,CAAC,MAAe,EAAE,EAAE;oBAClB,QAAQ,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;wBAC3B,KAAK,iCAAe,CAAC,OAAO,CAAC;wBAC7B,KAAK,iCAAe,CAAC,KAAK,CAAC;wBAC3B,KAAK,iCAAe,CAAC,SAAS;4BAC5B,2DAA2D;4BAC3D,4DAA4D;4BAC5D,+DAA+D;4BAE/D,mDAAmD;4BACnD,qDAAqD;4BACrD,sDAAsD;4BACtD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;4BACxB,OAAO;wBAET,KAAK,iCAAe,CAAC,OAAO,CAAC;wBAC7B,KAAK,iCAAe,CAAC,OAAO,CAAC;wBAC7B,KAAK,iCAAe,CAAC,OAAO,CAAC;wBAC7B,KAAK,iCAAe,CAAC,IAAI,CAAC;wBAC1B,KAAK,iCAAe,CAAC,OAAO;4BAC1B,wDAAwD;4BACxD,wDAAwD;4BACxD,mBAAmB;4BACnB,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;wBACvC;4BACE,8CAA8C;4BAC9C,MAAM,aAAa,GAAc,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC;4BACpD,MAAM,IAAI,iCAAa,CAAC,sBAAsB,aAAa,EAAE,CAAC,CAAC;oBACnE,CAAC;gBACH,CAAC;gBACH,CAAC,CAAC,SAAS;SACd,CAAC;QAEF,kDAAkD;QAClD,KAAK,CAAC,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,IAA8B,EAAE;YAClE,uDAAuD;YACvD,MAAM,UAAU,GAAoB,KAAK,CAAC;YAE1C,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACxB,UAAU,CAAC,MAAM,GAAG,iCAAe,CAAC,OAAO,CAAC;gBAC5C,OAAO,UAAU,CAAC,MAAM,CAAC;YAC3B,CAAC;YAED,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAExC,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC7B,UAAU,CAAC,MAAM,GAAG,iCAAe,CAAC,SAAS,CAAC;YAC9C,0DAA0D;YAC1D,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC;YAE7B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;gBACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBACzB,IAAI,CAAC;oBACH,mEAAmE;oBACnE,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,iCAAe,CAAC,IAAI,CAAC;gBAC9F,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,UAAU,CAAC,MAAM,GAAG,iCAAe,CAAC,OAAO,CAAC;oBAC5C,UAAU,CAAC,KAAK,GAAG,KAAuB,CAAC;gBAC7C,CAAC;gBAED,8FAA8F;gBAC9F,6FAA6F;gBAC7F,sBAAsB;gBAEtB,6FAA6F;gBAC7F,gGAAgG;gBAChG,qGAAqG;gBACrG,0FAA0F;gBAE1F,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;wBACxB,UAAU,CAAC,MAAM,GAAG,iCAAe,CAAC,OAAO,CAAC;wBAC5C,MAAM;oBACR,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;oBACtE,CAAC;gBACH,CAAC;YACH,CAAC;YAED,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAElC,OAAO,KAAK,CAAC,MAAM,CAAC;QACtB,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAC;QAEhD,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;CACF;AAhRD,8BAgRC","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 { InternalError } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { Stopwatch } from './Stopwatch';\nimport type {\n IOperationRunner,\n IOperationRunnerContext,\n IOperationState,\n IOperationStates\n} from './IOperationRunner';\nimport type { OperationError } from './OperationError';\nimport { OperationStatus } from './OperationStatus';\nimport type { OperationGroupRecord } from './OperationGroupRecord';\n\n/**\n * Options for constructing a new Operation.\n * @beta\n */\nexport interface IOperationOptions<TMetadata extends {} = {}, TGroupMetadata extends {} = {}> {\n /**\n * The name of this operation, for logging.\n */\n name: string;\n\n /**\n * The group that this operation belongs to. Will be used for logging and duration tracking.\n */\n group?: OperationGroupRecord<TGroupMetadata> | undefined;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n runner?: IOperationRunner | undefined;\n\n /**\n * The weight used by the scheduler to determine order of execution.\n */\n weight?: number | undefined;\n\n /**\n * The metadata for this operation.\n */\n metadata?: TMetadata | undefined;\n}\n\n/**\n * Type for the `requestRun` callback.\n * @beta\n */\nexport type OperationRequestRunCallback = (requestor: string, detail?: string) => void;\n\n/**\n * Information provided to `executeAsync` by the `OperationExecutionManager`.\n *\n * @beta\n */\nexport interface IExecuteOperationContext extends Omit<IOperationRunnerContext, 'isFirstRun' | 'requestRun'> {\n /**\n * Function to invoke before execution of an operation, for logging.\n */\n beforeExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function to invoke after execution of an operation, for logging.\n */\n afterExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function used to schedule the concurrency-limited execution of an operation.\n *\n * Will return OperationStatus.Aborted if execution is aborted before the task executes.\n */\n queueWork(workFn: () => Promise<OperationStatus>, priority: number): Promise<OperationStatus>;\n\n /**\n * A callback to the overarching orchestrator to request that the operation be invoked again.\n * Used in watch mode to signal that inputs have changed.\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 requestRun?: OperationRequestRunCallback;\n\n /**\n * Terminal to write output to.\n */\n terminal: ITerminal;\n}\n\n/**\n * The `Operation` class is a node in the dependency graph of work that needs to be scheduled by the\n * `OperationExecutionManager`. Each `Operation` has a `runner` member of type `IOperationRunner`, whose\n * implementation manages the actual process of running a single operation.\n *\n * The graph of `Operation` instances will be cloned into a separate execution graph after processing.\n *\n * @beta\n */\nexport class Operation<TMetadata extends {} = {}, TGroupMetadata extends {} = {}>\n implements IOperationStates\n{\n /**\n * A set of all dependencies which must be executed before this operation is complete.\n */\n public readonly dependencies: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * A set of all operations that wait for this operation.\n */\n public readonly consumers: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * If specified, the name of a grouping to which this Operation belongs, for logging start and end times.\n */\n public readonly group: OperationGroupRecord<TGroupMetadata> | undefined;\n /**\n * The name of this operation, for logging.\n */\n public readonly name: string;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n public runner: IOperationRunner | undefined = undefined;\n\n /**\n * This number represents how far away this Operation is from the furthest \"root\" operation (i.e.\n * an operation with no consumers). This helps us to calculate the critical path (i.e. the\n * longest chain of projects which must be executed in order, thereby limiting execution speed\n * of the entire operation tree.\n *\n * This number is calculated via a memoized depth-first search, and when choosing the next\n * operation to execute, the operation with the highest criticalPathLength is chosen.\n *\n * Example:\n * (0) A\n * \\\\\n * (1) B C (0) (applications)\n * \\\\ /|\\\\\n * \\\\ / | \\\\\n * (2) D | X (1) (utilities)\n * | / \\\\\n * |/ \\\\\n * (2) Y Z (2) (other utilities)\n *\n * All roots (A & C) have a criticalPathLength of 0.\n * B has a score of 1, since A depends on it.\n * D has a score of 2, since we look at the longest chain (e.g D-\\>B-\\>A is longer than D-\\>C)\n * X has a score of 1, since the only package which depends on it is A\n * Z has a score of 2, since only X depends on it, and X has a score of 1\n * Y has a score of 2, since the chain Y-\\>X-\\>C is longer than Y-\\>C\n *\n * The algorithm is implemented in AsyncOperationQueue.ts as calculateCriticalPathLength()\n */\n public criticalPathLength: number | undefined = undefined;\n\n /**\n * The weight for this operation. This scalar is the contribution of this operation to the\n * `criticalPathLength` calculation above. Modify to indicate the following:\n * - `weight` === 1: indicates that this operation has an average duration\n * - `weight` > 1: indicates that this operation takes longer than average and so the scheduler\n * should try to favor starting it over other, shorter operations. An example might be an operation that\n * bundles an entire application and runs whole-program optimization.\n * - `weight` < 1: indicates that this operation takes less time than average and so the scheduler\n * should favor other, longer operations over it. An example might be an operation to unpack a cached\n * output, or an operation using NullOperationRunner, which might use a value of 0.\n */\n public weight: number;\n\n /**\n * The state of this operation the previous time a manager was invoked.\n */\n public lastState: IOperationState | undefined = undefined;\n\n /**\n * The current state of this operation\n */\n public state: IOperationState | undefined = undefined;\n\n /**\n * A cached execution promise for the current OperationExecutionManager invocation of this operation.\n */\n private _promise: Promise<OperationStatus> | undefined = undefined;\n\n /**\n * If true, then a run of this operation is currently wanted.\n * This is used to track state from the `requestRun` callback passed to the runner.\n */\n private _runPending: boolean = true;\n\n public readonly metadata: TMetadata;\n\n public constructor(options: IOperationOptions<TMetadata, TGroupMetadata>) {\n this.group = options.group;\n this.runner = options.runner;\n this.weight = options.weight ?? 1;\n this.name = options.name;\n this.metadata = options.metadata || ({} as TMetadata);\n\n if (this.group) {\n this.group.addOperation(this);\n }\n }\n\n public addDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.add(dependency);\n dependency.consumers.add(this);\n }\n\n public deleteDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.delete(dependency);\n dependency.consumers.delete(this);\n }\n\n public reset(): void {\n // Reset operation state\n this.lastState = this.state;\n\n this.state = {\n status: this.dependencies.size > 0 ? OperationStatus.Waiting : OperationStatus.Ready,\n hasBeenRun: this.lastState?.hasBeenRun ?? false,\n error: undefined,\n stopwatch: new Stopwatch()\n };\n\n this._promise = undefined;\n this._runPending = true;\n }\n\n /**\n * @internal\n */\n public async _executeAsync(context: IExecuteOperationContext): Promise<OperationStatus> {\n const { state } = this;\n if (!state) {\n throw new Error(`Operation state has not been initialized.`);\n }\n\n if (!this._promise) {\n this._promise = this._executeInnerAsync(context, state);\n }\n\n return this._promise;\n }\n\n private async _executeInnerAsync(\n context: IExecuteOperationContext,\n rawState: IOperationState\n ): Promise<OperationStatus> {\n const state: IOperationState = rawState;\n const { runner } = this;\n\n const dependencyResults: PromiseSettledResult<OperationStatus>[] = await Promise.allSettled(\n Array.from(this.dependencies, (dependency: Operation) => dependency._executeAsync(context))\n );\n\n const { abortSignal, requestRun, queueWork } = context;\n\n if (abortSignal.aborted) {\n state.status = OperationStatus.Aborted;\n return state.status;\n }\n\n for (const result of dependencyResults) {\n if (\n result.status === 'rejected' ||\n result.value === OperationStatus.Blocked ||\n result.value === OperationStatus.Failure\n ) {\n state.status = OperationStatus.Blocked;\n return state.status;\n }\n }\n\n state.status = OperationStatus.Ready;\n\n const innerContext: IOperationRunnerContext = {\n abortSignal,\n isFirstRun: !state.hasBeenRun,\n requestRun: requestRun\n ? (detail?: string) => {\n switch (this.state?.status) {\n case OperationStatus.Waiting:\n case OperationStatus.Ready:\n case OperationStatus.Executing:\n // If current status has not yet resolved to a fixed value,\n // re-executing this operation does not require a full rerun\n // of the operation graph. Simply mark that a run is requested.\n\n // This variable is on the Operation instead of the\n // containing closure to deal with scenarios in which\n // the runner hangs on to an old copy of the callback.\n this._runPending = true;\n return;\n\n case OperationStatus.Blocked:\n case OperationStatus.Aborted:\n case OperationStatus.Failure:\n case OperationStatus.NoOp:\n case OperationStatus.Success:\n // The requestRun callback is assumed to remain constant\n // throughout the lifetime of the process, so it is safe\n // to capture here.\n return requestRun(this.name, detail);\n default:\n // This line is here to enforce exhaustiveness\n const currentStatus: undefined = this.state?.status;\n throw new InternalError(`Unexpected status: ${currentStatus}`);\n }\n }\n : undefined\n };\n\n // eslint-disable-next-line require-atomic-updates\n state.status = await queueWork(async (): Promise<OperationStatus> => {\n // Redundant variable to satisfy require-atomic-updates\n const innerState: IOperationState = state;\n\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n return innerState.status;\n }\n\n context.beforeExecute(this, innerState);\n\n innerState.stopwatch.start();\n innerState.status = OperationStatus.Executing;\n // Mark that the operation has been started at least once.\n innerState.hasBeenRun = true;\n\n while (this._runPending) {\n this._runPending = false;\n try {\n // We don't support aborting in the middle of a runner's execution.\n innerState.status = runner ? await runner.executeAsync(innerContext) : OperationStatus.NoOp;\n } catch (error) {\n innerState.status = OperationStatus.Failure;\n innerState.error = error as OperationError;\n }\n\n // Since runner.executeAsync is async, a change could have occurred that requires re-execution\n // This operation is still active, so can re-execute immediately, rather than forcing a whole\n // new execution pass.\n\n // As currently written, this does mean that if a job is scheduled with higher priority while\n // this operation is still executing, it will still wait for this retry. This may not be desired\n // and if it becomes a problem, the retry loop will need to be moved outside of the `queueWork` call.\n // This introduces complexity regarding tracking of timing and start/end logging, however.\n\n if (this._runPending) {\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n break;\n } else {\n context.terminal.writeLine(`Immediate rerun requested. Executing.`);\n }\n }\n }\n\n state.stopwatch.stop();\n context.afterExecute(this, state);\n\n return state.status;\n }, /* priority */ this.criticalPathLength ?? 0);\n\n return state.status;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Operation.js","sourceRoot":"","sources":["../src/Operation.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 { InternalError } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { Stopwatch } from './Stopwatch';\nimport type {\n IOperationRunner,\n IOperationRunnerContext,\n IOperationState,\n IOperationStates\n} from './IOperationRunner';\nimport type { OperationError } from './OperationError';\nimport { OperationStatus } from './OperationStatus';\nimport type { OperationGroupRecord } from './OperationGroupRecord';\n\n/**\n * Options for constructing a new Operation.\n * @beta\n */\nexport interface IOperationOptions<TMetadata extends {} = {}, TGroupMetadata extends {} = {}> {\n /**\n * The name of this operation, for logging.\n */\n name: string;\n\n /**\n * The group that this operation belongs to. Will be used for logging and duration tracking.\n */\n group?: OperationGroupRecord<TGroupMetadata> | undefined;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n runner?: IOperationRunner | undefined;\n\n /**\n * The weight used by the scheduler to determine order of execution.\n */\n weight?: number | undefined;\n\n /**\n * The metadata for this operation.\n */\n metadata?: TMetadata | undefined;\n}\n\n/**\n * Type for the `requestRun` callback.\n * @beta\n */\nexport type OperationRequestRunCallback = (requestor: string, detail?: string) => void;\n\n/**\n * Information provided to `executeAsync` by the `OperationExecutionManager`.\n *\n * @beta\n */\nexport interface IExecuteOperationContext extends Omit<IOperationRunnerContext, 'isFirstRun' | 'requestRun'> {\n /**\n * Function to invoke before execution of an operation, for logging.\n */\n beforeExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function to invoke after execution of an operation, for logging.\n */\n afterExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function used to schedule the concurrency-limited execution of an operation.\n *\n * Will return OperationStatus.Aborted if execution is aborted before the task executes.\n */\n queueWork(workFn: () => Promise<OperationStatus>, priority: number): Promise<OperationStatus>;\n\n /**\n * A callback to the overarching orchestrator to request that the operation be invoked again.\n * Used in watch mode to signal that inputs have changed.\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 requestRun?: OperationRequestRunCallback;\n\n /**\n * Terminal to write output to.\n */\n terminal: ITerminal;\n}\n\n/**\n * The `Operation` class is a node in the dependency graph of work that needs to be scheduled by the\n * `OperationExecutionManager`. Each `Operation` has a `runner` member of type `IOperationRunner`, whose\n * implementation manages the actual process of running a single operation.\n *\n * The graph of `Operation` instances will be cloned into a separate execution graph after processing.\n *\n * @beta\n */\nexport class Operation<TMetadata extends {} = {}, TGroupMetadata extends {} = {}>\n implements IOperationStates\n{\n /**\n * A set of all dependencies which must be executed before this operation is complete.\n */\n public readonly dependencies: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * A set of all operations that wait for this operation.\n */\n public readonly consumers: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * If specified, the name of a grouping to which this Operation belongs, for logging start and end times.\n */\n public readonly group: OperationGroupRecord<TGroupMetadata> | undefined;\n /**\n * The name of this operation, for logging.\n */\n public readonly name: string;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n public runner: IOperationRunner | undefined = undefined;\n\n /**\n * This number represents how far away this Operation is from the furthest \"root\" operation (i.e.\n * an operation with no consumers). This helps us to calculate the critical path (i.e. the\n * longest chain of projects which must be executed in order, thereby limiting execution speed\n * of the entire operation tree.\n *\n * This number is calculated via a memoized depth-first search, and when choosing the next\n * operation to execute, the operation with the highest criticalPathLength is chosen.\n *\n * Example:\n * (0) A\n * \\\\\n * (1) B C (0) (applications)\n * \\\\ /|\\\\\n * \\\\ / | \\\\\n * (2) D | X (1) (utilities)\n * | / \\\\\n * |/ \\\\\n * (2) Y Z (2) (other utilities)\n *\n * All roots (A & C) have a criticalPathLength of 0.\n * B has a score of 1, since A depends on it.\n * D has a score of 2, since we look at the longest chain (e.g D-\\>B-\\>A is longer than D-\\>C)\n * X has a score of 1, since the only package which depends on it is A\n * Z has a score of 2, since only X depends on it, and X has a score of 1\n * Y has a score of 2, since the chain Y-\\>X-\\>C is longer than Y-\\>C\n *\n * The algorithm is implemented in AsyncOperationQueue.ts as calculateCriticalPathLength()\n */\n public criticalPathLength: number | undefined = undefined;\n\n /**\n * The weight for this operation. This scalar is the contribution of this operation to the\n * `criticalPathLength` calculation above. Modify to indicate the following:\n * - `weight` === 1: indicates that this operation has an average duration\n * - `weight` > 1: indicates that this operation takes longer than average and so the scheduler\n * should try to favor starting it over other, shorter operations. An example might be an operation that\n * bundles an entire application and runs whole-program optimization.\n * - `weight` < 1: indicates that this operation takes less time than average and so the scheduler\n * should favor other, longer operations over it. An example might be an operation to unpack a cached\n * output, or an operation using NullOperationRunner, which might use a value of 0.\n */\n public weight: number;\n\n /**\n * The state of this operation the previous time a manager was invoked.\n */\n public lastState: IOperationState | undefined = undefined;\n\n /**\n * The current state of this operation\n */\n public state: IOperationState | undefined = undefined;\n\n /**\n * A cached execution promise for the current OperationExecutionManager invocation of this operation.\n */\n private _promise: Promise<OperationStatus> | undefined = undefined;\n\n /**\n * If true, then a run of this operation is currently wanted.\n * This is used to track state from the `requestRun` callback passed to the runner.\n */\n private _runPending: boolean = true;\n\n public readonly metadata: TMetadata;\n\n public constructor(options: IOperationOptions<TMetadata, TGroupMetadata>) {\n const { group, runner, weight = 1, name, metadata = {} as TMetadata } = options;\n this.group = group;\n this.runner = runner;\n this.weight = weight;\n this.name = name;\n this.metadata = metadata;\n\n if (this.group) {\n this.group.addOperation(this);\n }\n }\n\n public addDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.add(dependency);\n dependency.consumers.add(this);\n }\n\n public deleteDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.delete(dependency);\n dependency.consumers.delete(this);\n }\n\n public reset(): void {\n // Reset operation state\n this.lastState = this.state;\n\n this.state = {\n status: this.dependencies.size > 0 ? OperationStatus.Waiting : OperationStatus.Ready,\n hasBeenRun: this.lastState?.hasBeenRun ?? false,\n error: undefined,\n stopwatch: new Stopwatch()\n };\n\n this._promise = undefined;\n this._runPending = true;\n }\n\n /**\n * @internal\n */\n public async _executeAsync(context: IExecuteOperationContext): Promise<OperationStatus> {\n const { state } = this;\n if (!state) {\n throw new Error(`Operation state has not been initialized.`);\n }\n\n if (!this._promise) {\n this._promise = this._executeInnerAsync(context, state);\n }\n\n return this._promise;\n }\n\n private async _executeInnerAsync(\n context: IExecuteOperationContext,\n rawState: IOperationState\n ): Promise<OperationStatus> {\n const state: IOperationState = rawState;\n const { runner } = this;\n\n const dependencyResults: PromiseSettledResult<OperationStatus>[] = await Promise.allSettled(\n Array.from(this.dependencies, (dependency: Operation) => dependency._executeAsync(context))\n );\n\n const { abortSignal, requestRun, queueWork } = context;\n\n if (abortSignal.aborted) {\n state.status = OperationStatus.Aborted;\n return state.status;\n }\n\n for (const result of dependencyResults) {\n if (\n result.status === 'rejected' ||\n result.value === OperationStatus.Blocked ||\n result.value === OperationStatus.Failure\n ) {\n state.status = OperationStatus.Blocked;\n return state.status;\n }\n }\n\n state.status = OperationStatus.Ready;\n\n const innerContext: IOperationRunnerContext = {\n abortSignal,\n isFirstRun: !state.hasBeenRun,\n requestRun: requestRun\n ? (detail?: string) => {\n switch (this.state?.status) {\n case OperationStatus.Waiting:\n case OperationStatus.Ready:\n case OperationStatus.Executing:\n // If current status has not yet resolved to a fixed value,\n // re-executing this operation does not require a full rerun\n // of the operation graph. Simply mark that a run is requested.\n\n // This variable is on the Operation instead of the\n // containing closure to deal with scenarios in which\n // the runner hangs on to an old copy of the callback.\n this._runPending = true;\n return;\n\n case OperationStatus.Blocked:\n case OperationStatus.Aborted:\n case OperationStatus.Failure:\n case OperationStatus.NoOp:\n case OperationStatus.Success:\n // The requestRun callback is assumed to remain constant\n // throughout the lifetime of the process, so it is safe\n // to capture here.\n return requestRun(this.name, detail);\n default:\n // This line is here to enforce exhaustiveness\n const currentStatus: undefined = this.state?.status;\n throw new InternalError(`Unexpected status: ${currentStatus}`);\n }\n }\n : undefined\n };\n\n // eslint-disable-next-line require-atomic-updates\n state.status = await queueWork(async (): Promise<OperationStatus> => {\n // Redundant variable to satisfy require-atomic-updates\n const innerState: IOperationState = state;\n\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n return innerState.status;\n }\n\n context.beforeExecute(this, innerState);\n\n innerState.stopwatch.start();\n innerState.status = OperationStatus.Executing;\n // Mark that the operation has been started at least once.\n innerState.hasBeenRun = true;\n\n while (this._runPending) {\n this._runPending = false;\n try {\n // We don't support aborting in the middle of a runner's execution.\n innerState.status = runner ? await runner.executeAsync(innerContext) : OperationStatus.NoOp;\n } catch (error) {\n innerState.status = OperationStatus.Failure;\n innerState.error = error as OperationError;\n }\n\n // Since runner.executeAsync is async, a change could have occurred that requires re-execution\n // This operation is still active, so can re-execute immediately, rather than forcing a whole\n // new execution pass.\n\n // As currently written, this does mean that if a job is scheduled with higher priority while\n // this operation is still executing, it will still wait for this retry. This may not be desired\n // and if it becomes a problem, the retry loop will need to be moved outside of the `queueWork` call.\n // This introduces complexity regarding tracking of timing and start/end logging, however.\n\n if (this._runPending) {\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n break;\n } else {\n context.terminal.writeLine(`Immediate rerun requested. Executing.`);\n }\n }\n }\n\n state.stopwatch.stop();\n context.afterExecute(this, state);\n\n return state.status;\n }, /* priority */ this.criticalPathLength ?? 0);\n\n return state.status;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Operation.d.ts","sourceRoot":"","sources":["../src/Operation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,EAAE,cAAc,SAAS,EAAE,GAAG,EAAE;IAC1F;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,KAAK,CAAC,EAAE,oBAAoB,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEzD;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAEtC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvF;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,uBAAuB,EAAE,YAAY,GAAG,YAAY,CAAC;IAC1G;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAElE;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAEjE;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE9F;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAS,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,EAAE,cAAc,SAAS,EAAE,GAAG,EAAE,CAC9E,YAAW,gBAAgB;IAE3B;;OAEG;IACH,SAAgB,YAAY,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAEnE;IACJ;;OAEG;IACH,SAAgB,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAEhE;IACJ;;OAEG;IACH,SAAgB,KAAK,EAAE,oBAAoB,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IACxE;;OAEG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACI,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAa;IAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACI,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAa;IAE1D;;;;;;;;;;OAUG;IACI,MAAM,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACI,SAAS,EAAE,eAAe,GAAG,SAAS,CAAa;IAE1D;;OAEG;IACI,KAAK,EAAE,eAAe,GAAG,SAAS,CAAa;IAEtD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAmD;IAEnE;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAiB;IAEpC,SAAgB,QAAQ,EAAE,SAAS,CAAC;gBAEjB,OAAO,EAAE,iBAAiB,CAAC,SAAS,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Operation.d.ts","sourceRoot":"","sources":["../src/Operation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,EAAE,cAAc,SAAS,EAAE,GAAG,EAAE;IAC1F;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,KAAK,CAAC,EAAE,oBAAoB,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEzD;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAEtC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvF;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,uBAAuB,EAAE,YAAY,GAAG,YAAY,CAAC;IAC1G;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAElE;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAEjE;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE9F;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAS,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,EAAE,cAAc,SAAS,EAAE,GAAG,EAAE,CAC9E,YAAW,gBAAgB;IAE3B;;OAEG;IACH,SAAgB,YAAY,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAEnE;IACJ;;OAEG;IACH,SAAgB,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAEhE;IACJ;;OAEG;IACH,SAAgB,KAAK,EAAE,oBAAoB,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IACxE;;OAEG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACI,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAa;IAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACI,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAa;IAE1D;;;;;;;;;;OAUG;IACI,MAAM,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACI,SAAS,EAAE,eAAe,GAAG,SAAS,CAAa;IAE1D;;OAEG;IACI,KAAK,EAAE,eAAe,GAAG,SAAS,CAAa;IAEtD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAmD;IAEnE;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAiB;IAEpC,SAAgB,QAAQ,EAAE,SAAS,CAAC;gBAEjB,OAAO,EAAE,iBAAiB,CAAC,SAAS,EAAE,cAAc,CAAC;IAajE,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,GAAG,IAAI;IAKrE,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,GAAG,IAAI;IAKxE,KAAK,IAAI,IAAI;IAepB;;OAEG;IACU,aAAa,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC;YAazE,kBAAkB;CA0HjC"}
|
package/lib-esm/Operation.js
CHANGED
|
@@ -74,11 +74,12 @@ export class Operation {
|
|
|
74
74
|
* This is used to track state from the `requestRun` callback passed to the runner.
|
|
75
75
|
*/
|
|
76
76
|
this._runPending = true;
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
77
|
+
const { group, runner, weight = 1, name, metadata = {} } = options;
|
|
78
|
+
this.group = group;
|
|
79
|
+
this.runner = runner;
|
|
80
|
+
this.weight = weight;
|
|
81
|
+
this.name = name;
|
|
82
|
+
this.metadata = metadata;
|
|
82
83
|
if (this.group) {
|
|
83
84
|
this.group.addOperation(this);
|
|
84
85
|
}
|
package/lib-esm/Operation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Operation.js","sourceRoot":"","sources":["../src/Operation.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 { InternalError } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { Stopwatch } from './Stopwatch';\nimport type {\n IOperationRunner,\n IOperationRunnerContext,\n IOperationState,\n IOperationStates\n} from './IOperationRunner';\nimport type { OperationError } from './OperationError';\nimport { OperationStatus } from './OperationStatus';\nimport type { OperationGroupRecord } from './OperationGroupRecord';\n\n/**\n * Options for constructing a new Operation.\n * @beta\n */\nexport interface IOperationOptions<TMetadata extends {} = {}, TGroupMetadata extends {} = {}> {\n /**\n * The name of this operation, for logging.\n */\n name: string;\n\n /**\n * The group that this operation belongs to. Will be used for logging and duration tracking.\n */\n group?: OperationGroupRecord<TGroupMetadata> | undefined;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n runner?: IOperationRunner | undefined;\n\n /**\n * The weight used by the scheduler to determine order of execution.\n */\n weight?: number | undefined;\n\n /**\n * The metadata for this operation.\n */\n metadata?: TMetadata | undefined;\n}\n\n/**\n * Type for the `requestRun` callback.\n * @beta\n */\nexport type OperationRequestRunCallback = (requestor: string, detail?: string) => void;\n\n/**\n * Information provided to `executeAsync` by the `OperationExecutionManager`.\n *\n * @beta\n */\nexport interface IExecuteOperationContext extends Omit<IOperationRunnerContext, 'isFirstRun' | 'requestRun'> {\n /**\n * Function to invoke before execution of an operation, for logging.\n */\n beforeExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function to invoke after execution of an operation, for logging.\n */\n afterExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function used to schedule the concurrency-limited execution of an operation.\n *\n * Will return OperationStatus.Aborted if execution is aborted before the task executes.\n */\n queueWork(workFn: () => Promise<OperationStatus>, priority: number): Promise<OperationStatus>;\n\n /**\n * A callback to the overarching orchestrator to request that the operation be invoked again.\n * Used in watch mode to signal that inputs have changed.\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 requestRun?: OperationRequestRunCallback;\n\n /**\n * Terminal to write output to.\n */\n terminal: ITerminal;\n}\n\n/**\n * The `Operation` class is a node in the dependency graph of work that needs to be scheduled by the\n * `OperationExecutionManager`. Each `Operation` has a `runner` member of type `IOperationRunner`, whose\n * implementation manages the actual process of running a single operation.\n *\n * The graph of `Operation` instances will be cloned into a separate execution graph after processing.\n *\n * @beta\n */\nexport class Operation<TMetadata extends {} = {}, TGroupMetadata extends {} = {}>\n implements IOperationStates\n{\n /**\n * A set of all dependencies which must be executed before this operation is complete.\n */\n public readonly dependencies: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * A set of all operations that wait for this operation.\n */\n public readonly consumers: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * If specified, the name of a grouping to which this Operation belongs, for logging start and end times.\n */\n public readonly group: OperationGroupRecord<TGroupMetadata> | undefined;\n /**\n * The name of this operation, for logging.\n */\n public readonly name: string;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n public runner: IOperationRunner | undefined = undefined;\n\n /**\n * This number represents how far away this Operation is from the furthest \"root\" operation (i.e.\n * an operation with no consumers). This helps us to calculate the critical path (i.e. the\n * longest chain of projects which must be executed in order, thereby limiting execution speed\n * of the entire operation tree.\n *\n * This number is calculated via a memoized depth-first search, and when choosing the next\n * operation to execute, the operation with the highest criticalPathLength is chosen.\n *\n * Example:\n * (0) A\n * \\\\\n * (1) B C (0) (applications)\n * \\\\ /|\\\\\n * \\\\ / | \\\\\n * (2) D | X (1) (utilities)\n * | / \\\\\n * |/ \\\\\n * (2) Y Z (2) (other utilities)\n *\n * All roots (A & C) have a criticalPathLength of 0.\n * B has a score of 1, since A depends on it.\n * D has a score of 2, since we look at the longest chain (e.g D-\\>B-\\>A is longer than D-\\>C)\n * X has a score of 1, since the only package which depends on it is A\n * Z has a score of 2, since only X depends on it, and X has a score of 1\n * Y has a score of 2, since the chain Y-\\>X-\\>C is longer than Y-\\>C\n *\n * The algorithm is implemented in AsyncOperationQueue.ts as calculateCriticalPathLength()\n */\n public criticalPathLength: number | undefined = undefined;\n\n /**\n * The weight for this operation. This scalar is the contribution of this operation to the\n * `criticalPathLength` calculation above. Modify to indicate the following:\n * - `weight` === 1: indicates that this operation has an average duration\n * - `weight` > 1: indicates that this operation takes longer than average and so the scheduler\n * should try to favor starting it over other, shorter operations. An example might be an operation that\n * bundles an entire application and runs whole-program optimization.\n * - `weight` < 1: indicates that this operation takes less time than average and so the scheduler\n * should favor other, longer operations over it. An example might be an operation to unpack a cached\n * output, or an operation using NullOperationRunner, which might use a value of 0.\n */\n public weight: number;\n\n /**\n * The state of this operation the previous time a manager was invoked.\n */\n public lastState: IOperationState | undefined = undefined;\n\n /**\n * The current state of this operation\n */\n public state: IOperationState | undefined = undefined;\n\n /**\n * A cached execution promise for the current OperationExecutionManager invocation of this operation.\n */\n private _promise: Promise<OperationStatus> | undefined = undefined;\n\n /**\n * If true, then a run of this operation is currently wanted.\n * This is used to track state from the `requestRun` callback passed to the runner.\n */\n private _runPending: boolean = true;\n\n public readonly metadata: TMetadata;\n\n public constructor(options: IOperationOptions<TMetadata, TGroupMetadata>) {\n this.group = options.group;\n this.runner = options.runner;\n this.weight = options.weight ?? 1;\n this.name = options.name;\n this.metadata = options.metadata || ({} as TMetadata);\n\n if (this.group) {\n this.group.addOperation(this);\n }\n }\n\n public addDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.add(dependency);\n dependency.consumers.add(this);\n }\n\n public deleteDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.delete(dependency);\n dependency.consumers.delete(this);\n }\n\n public reset(): void {\n // Reset operation state\n this.lastState = this.state;\n\n this.state = {\n status: this.dependencies.size > 0 ? OperationStatus.Waiting : OperationStatus.Ready,\n hasBeenRun: this.lastState?.hasBeenRun ?? false,\n error: undefined,\n stopwatch: new Stopwatch()\n };\n\n this._promise = undefined;\n this._runPending = true;\n }\n\n /**\n * @internal\n */\n public async _executeAsync(context: IExecuteOperationContext): Promise<OperationStatus> {\n const { state } = this;\n if (!state) {\n throw new Error(`Operation state has not been initialized.`);\n }\n\n if (!this._promise) {\n this._promise = this._executeInnerAsync(context, state);\n }\n\n return this._promise;\n }\n\n private async _executeInnerAsync(\n context: IExecuteOperationContext,\n rawState: IOperationState\n ): Promise<OperationStatus> {\n const state: IOperationState = rawState;\n const { runner } = this;\n\n const dependencyResults: PromiseSettledResult<OperationStatus>[] = await Promise.allSettled(\n Array.from(this.dependencies, (dependency: Operation) => dependency._executeAsync(context))\n );\n\n const { abortSignal, requestRun, queueWork } = context;\n\n if (abortSignal.aborted) {\n state.status = OperationStatus.Aborted;\n return state.status;\n }\n\n for (const result of dependencyResults) {\n if (\n result.status === 'rejected' ||\n result.value === OperationStatus.Blocked ||\n result.value === OperationStatus.Failure\n ) {\n state.status = OperationStatus.Blocked;\n return state.status;\n }\n }\n\n state.status = OperationStatus.Ready;\n\n const innerContext: IOperationRunnerContext = {\n abortSignal,\n isFirstRun: !state.hasBeenRun,\n requestRun: requestRun\n ? (detail?: string) => {\n switch (this.state?.status) {\n case OperationStatus.Waiting:\n case OperationStatus.Ready:\n case OperationStatus.Executing:\n // If current status has not yet resolved to a fixed value,\n // re-executing this operation does not require a full rerun\n // of the operation graph. Simply mark that a run is requested.\n\n // This variable is on the Operation instead of the\n // containing closure to deal with scenarios in which\n // the runner hangs on to an old copy of the callback.\n this._runPending = true;\n return;\n\n case OperationStatus.Blocked:\n case OperationStatus.Aborted:\n case OperationStatus.Failure:\n case OperationStatus.NoOp:\n case OperationStatus.Success:\n // The requestRun callback is assumed to remain constant\n // throughout the lifetime of the process, so it is safe\n // to capture here.\n return requestRun(this.name, detail);\n default:\n // This line is here to enforce exhaustiveness\n const currentStatus: undefined = this.state?.status;\n throw new InternalError(`Unexpected status: ${currentStatus}`);\n }\n }\n : undefined\n };\n\n // eslint-disable-next-line require-atomic-updates\n state.status = await queueWork(async (): Promise<OperationStatus> => {\n // Redundant variable to satisfy require-atomic-updates\n const innerState: IOperationState = state;\n\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n return innerState.status;\n }\n\n context.beforeExecute(this, innerState);\n\n innerState.stopwatch.start();\n innerState.status = OperationStatus.Executing;\n // Mark that the operation has been started at least once.\n innerState.hasBeenRun = true;\n\n while (this._runPending) {\n this._runPending = false;\n try {\n // We don't support aborting in the middle of a runner's execution.\n innerState.status = runner ? await runner.executeAsync(innerContext) : OperationStatus.NoOp;\n } catch (error) {\n innerState.status = OperationStatus.Failure;\n innerState.error = error as OperationError;\n }\n\n // Since runner.executeAsync is async, a change could have occurred that requires re-execution\n // This operation is still active, so can re-execute immediately, rather than forcing a whole\n // new execution pass.\n\n // As currently written, this does mean that if a job is scheduled with higher priority while\n // this operation is still executing, it will still wait for this retry. This may not be desired\n // and if it becomes a problem, the retry loop will need to be moved outside of the `queueWork` call.\n // This introduces complexity regarding tracking of timing and start/end logging, however.\n\n if (this._runPending) {\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n break;\n } else {\n context.terminal.writeLine(`Immediate rerun requested. Executing.`);\n }\n }\n }\n\n state.stopwatch.stop();\n context.afterExecute(this, state);\n\n return state.status;\n }, /* priority */ this.criticalPathLength ?? 0);\n\n return state.status;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Operation.js","sourceRoot":"","sources":["../src/Operation.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 { InternalError } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { Stopwatch } from './Stopwatch';\nimport type {\n IOperationRunner,\n IOperationRunnerContext,\n IOperationState,\n IOperationStates\n} from './IOperationRunner';\nimport type { OperationError } from './OperationError';\nimport { OperationStatus } from './OperationStatus';\nimport type { OperationGroupRecord } from './OperationGroupRecord';\n\n/**\n * Options for constructing a new Operation.\n * @beta\n */\nexport interface IOperationOptions<TMetadata extends {} = {}, TGroupMetadata extends {} = {}> {\n /**\n * The name of this operation, for logging.\n */\n name: string;\n\n /**\n * The group that this operation belongs to. Will be used for logging and duration tracking.\n */\n group?: OperationGroupRecord<TGroupMetadata> | undefined;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n runner?: IOperationRunner | undefined;\n\n /**\n * The weight used by the scheduler to determine order of execution.\n */\n weight?: number | undefined;\n\n /**\n * The metadata for this operation.\n */\n metadata?: TMetadata | undefined;\n}\n\n/**\n * Type for the `requestRun` callback.\n * @beta\n */\nexport type OperationRequestRunCallback = (requestor: string, detail?: string) => void;\n\n/**\n * Information provided to `executeAsync` by the `OperationExecutionManager`.\n *\n * @beta\n */\nexport interface IExecuteOperationContext extends Omit<IOperationRunnerContext, 'isFirstRun' | 'requestRun'> {\n /**\n * Function to invoke before execution of an operation, for logging.\n */\n beforeExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function to invoke after execution of an operation, for logging.\n */\n afterExecute(operation: Operation, state: IOperationState): void;\n\n /**\n * Function used to schedule the concurrency-limited execution of an operation.\n *\n * Will return OperationStatus.Aborted if execution is aborted before the task executes.\n */\n queueWork(workFn: () => Promise<OperationStatus>, priority: number): Promise<OperationStatus>;\n\n /**\n * A callback to the overarching orchestrator to request that the operation be invoked again.\n * Used in watch mode to signal that inputs have changed.\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 requestRun?: OperationRequestRunCallback;\n\n /**\n * Terminal to write output to.\n */\n terminal: ITerminal;\n}\n\n/**\n * The `Operation` class is a node in the dependency graph of work that needs to be scheduled by the\n * `OperationExecutionManager`. Each `Operation` has a `runner` member of type `IOperationRunner`, whose\n * implementation manages the actual process of running a single operation.\n *\n * The graph of `Operation` instances will be cloned into a separate execution graph after processing.\n *\n * @beta\n */\nexport class Operation<TMetadata extends {} = {}, TGroupMetadata extends {} = {}>\n implements IOperationStates\n{\n /**\n * A set of all dependencies which must be executed before this operation is complete.\n */\n public readonly dependencies: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * A set of all operations that wait for this operation.\n */\n public readonly consumers: Set<Operation<TMetadata, TGroupMetadata>> = new Set<\n Operation<TMetadata, TGroupMetadata>\n >();\n /**\n * If specified, the name of a grouping to which this Operation belongs, for logging start and end times.\n */\n public readonly group: OperationGroupRecord<TGroupMetadata> | undefined;\n /**\n * The name of this operation, for logging.\n */\n public readonly name: string;\n\n /**\n * When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of\n * running the operation.\n */\n public runner: IOperationRunner | undefined = undefined;\n\n /**\n * This number represents how far away this Operation is from the furthest \"root\" operation (i.e.\n * an operation with no consumers). This helps us to calculate the critical path (i.e. the\n * longest chain of projects which must be executed in order, thereby limiting execution speed\n * of the entire operation tree.\n *\n * This number is calculated via a memoized depth-first search, and when choosing the next\n * operation to execute, the operation with the highest criticalPathLength is chosen.\n *\n * Example:\n * (0) A\n * \\\\\n * (1) B C (0) (applications)\n * \\\\ /|\\\\\n * \\\\ / | \\\\\n * (2) D | X (1) (utilities)\n * | / \\\\\n * |/ \\\\\n * (2) Y Z (2) (other utilities)\n *\n * All roots (A & C) have a criticalPathLength of 0.\n * B has a score of 1, since A depends on it.\n * D has a score of 2, since we look at the longest chain (e.g D-\\>B-\\>A is longer than D-\\>C)\n * X has a score of 1, since the only package which depends on it is A\n * Z has a score of 2, since only X depends on it, and X has a score of 1\n * Y has a score of 2, since the chain Y-\\>X-\\>C is longer than Y-\\>C\n *\n * The algorithm is implemented in AsyncOperationQueue.ts as calculateCriticalPathLength()\n */\n public criticalPathLength: number | undefined = undefined;\n\n /**\n * The weight for this operation. This scalar is the contribution of this operation to the\n * `criticalPathLength` calculation above. Modify to indicate the following:\n * - `weight` === 1: indicates that this operation has an average duration\n * - `weight` > 1: indicates that this operation takes longer than average and so the scheduler\n * should try to favor starting it over other, shorter operations. An example might be an operation that\n * bundles an entire application and runs whole-program optimization.\n * - `weight` < 1: indicates that this operation takes less time than average and so the scheduler\n * should favor other, longer operations over it. An example might be an operation to unpack a cached\n * output, or an operation using NullOperationRunner, which might use a value of 0.\n */\n public weight: number;\n\n /**\n * The state of this operation the previous time a manager was invoked.\n */\n public lastState: IOperationState | undefined = undefined;\n\n /**\n * The current state of this operation\n */\n public state: IOperationState | undefined = undefined;\n\n /**\n * A cached execution promise for the current OperationExecutionManager invocation of this operation.\n */\n private _promise: Promise<OperationStatus> | undefined = undefined;\n\n /**\n * If true, then a run of this operation is currently wanted.\n * This is used to track state from the `requestRun` callback passed to the runner.\n */\n private _runPending: boolean = true;\n\n public readonly metadata: TMetadata;\n\n public constructor(options: IOperationOptions<TMetadata, TGroupMetadata>) {\n const { group, runner, weight = 1, name, metadata = {} as TMetadata } = options;\n this.group = group;\n this.runner = runner;\n this.weight = weight;\n this.name = name;\n this.metadata = metadata;\n\n if (this.group) {\n this.group.addOperation(this);\n }\n }\n\n public addDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.add(dependency);\n dependency.consumers.add(this);\n }\n\n public deleteDependency(dependency: Operation<TMetadata, TGroupMetadata>): void {\n this.dependencies.delete(dependency);\n dependency.consumers.delete(this);\n }\n\n public reset(): void {\n // Reset operation state\n this.lastState = this.state;\n\n this.state = {\n status: this.dependencies.size > 0 ? OperationStatus.Waiting : OperationStatus.Ready,\n hasBeenRun: this.lastState?.hasBeenRun ?? false,\n error: undefined,\n stopwatch: new Stopwatch()\n };\n\n this._promise = undefined;\n this._runPending = true;\n }\n\n /**\n * @internal\n */\n public async _executeAsync(context: IExecuteOperationContext): Promise<OperationStatus> {\n const { state } = this;\n if (!state) {\n throw new Error(`Operation state has not been initialized.`);\n }\n\n if (!this._promise) {\n this._promise = this._executeInnerAsync(context, state);\n }\n\n return this._promise;\n }\n\n private async _executeInnerAsync(\n context: IExecuteOperationContext,\n rawState: IOperationState\n ): Promise<OperationStatus> {\n const state: IOperationState = rawState;\n const { runner } = this;\n\n const dependencyResults: PromiseSettledResult<OperationStatus>[] = await Promise.allSettled(\n Array.from(this.dependencies, (dependency: Operation) => dependency._executeAsync(context))\n );\n\n const { abortSignal, requestRun, queueWork } = context;\n\n if (abortSignal.aborted) {\n state.status = OperationStatus.Aborted;\n return state.status;\n }\n\n for (const result of dependencyResults) {\n if (\n result.status === 'rejected' ||\n result.value === OperationStatus.Blocked ||\n result.value === OperationStatus.Failure\n ) {\n state.status = OperationStatus.Blocked;\n return state.status;\n }\n }\n\n state.status = OperationStatus.Ready;\n\n const innerContext: IOperationRunnerContext = {\n abortSignal,\n isFirstRun: !state.hasBeenRun,\n requestRun: requestRun\n ? (detail?: string) => {\n switch (this.state?.status) {\n case OperationStatus.Waiting:\n case OperationStatus.Ready:\n case OperationStatus.Executing:\n // If current status has not yet resolved to a fixed value,\n // re-executing this operation does not require a full rerun\n // of the operation graph. Simply mark that a run is requested.\n\n // This variable is on the Operation instead of the\n // containing closure to deal with scenarios in which\n // the runner hangs on to an old copy of the callback.\n this._runPending = true;\n return;\n\n case OperationStatus.Blocked:\n case OperationStatus.Aborted:\n case OperationStatus.Failure:\n case OperationStatus.NoOp:\n case OperationStatus.Success:\n // The requestRun callback is assumed to remain constant\n // throughout the lifetime of the process, so it is safe\n // to capture here.\n return requestRun(this.name, detail);\n default:\n // This line is here to enforce exhaustiveness\n const currentStatus: undefined = this.state?.status;\n throw new InternalError(`Unexpected status: ${currentStatus}`);\n }\n }\n : undefined\n };\n\n // eslint-disable-next-line require-atomic-updates\n state.status = await queueWork(async (): Promise<OperationStatus> => {\n // Redundant variable to satisfy require-atomic-updates\n const innerState: IOperationState = state;\n\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n return innerState.status;\n }\n\n context.beforeExecute(this, innerState);\n\n innerState.stopwatch.start();\n innerState.status = OperationStatus.Executing;\n // Mark that the operation has been started at least once.\n innerState.hasBeenRun = true;\n\n while (this._runPending) {\n this._runPending = false;\n try {\n // We don't support aborting in the middle of a runner's execution.\n innerState.status = runner ? await runner.executeAsync(innerContext) : OperationStatus.NoOp;\n } catch (error) {\n innerState.status = OperationStatus.Failure;\n innerState.error = error as OperationError;\n }\n\n // Since runner.executeAsync is async, a change could have occurred that requires re-execution\n // This operation is still active, so can re-execute immediately, rather than forcing a whole\n // new execution pass.\n\n // As currently written, this does mean that if a job is scheduled with higher priority while\n // this operation is still executing, it will still wait for this retry. This may not be desired\n // and if it becomes a problem, the retry loop will need to be moved outside of the `queueWork` call.\n // This introduces complexity regarding tracking of timing and start/end logging, however.\n\n if (this._runPending) {\n if (abortSignal.aborted) {\n innerState.status = OperationStatus.Aborted;\n break;\n } else {\n context.terminal.writeLine(`Immediate rerun requested. Executing.`);\n }\n }\n }\n\n state.stopwatch.stop();\n context.afterExecute(this, state);\n\n return state.status;\n }, /* priority */ this.criticalPathLength ?? 0);\n\n return state.status;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rushstack/operation-graph",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "Library for managing and executing operations in a directed acyclic graph.",
|
|
5
5
|
"main": "./lib-commonjs/index.js",
|
|
6
6
|
"module": "./lib-esm/index.js",
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"directory": "libraries/operation-graph"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@rushstack/
|
|
38
|
-
"@rushstack/
|
|
37
|
+
"@rushstack/node-core-library": "5.22.0",
|
|
38
|
+
"@rushstack/terminal": "0.22.5"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@rushstack/heft": "1.2.
|
|
41
|
+
"@rushstack/heft": "1.2.7",
|
|
42
42
|
"eslint": "~9.37.0",
|
|
43
43
|
"decoupled-local-node-rig": "1.0.0"
|
|
44
44
|
},
|