@rushstack/operation-graph
Version:
Library for managing and executing operations in a directed acyclic graph.
157 lines • 6.53 kB
TypeScript
import type { ITerminal } from '@rushstack/terminal';
import type { IOperationRunner, IOperationRunnerContext, IOperationState, IOperationStates } from './IOperationRunner';
import { OperationStatus } from './OperationStatus';
/**
* Options for constructing a new Operation.
* @beta
*/
export interface IOperationOptions {
/**
* The name of this operation, for logging.
*/
name?: string | undefined;
/**
* The group that this operation belongs to. Will be used for logging and duration tracking.
*/
groupName?: string | undefined;
/**
* When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of
* running the operation.
*/
runner?: IOperationRunner | undefined;
/**
* The weight used by the scheduler to determine order of execution.
*/
weight?: number | undefined;
}
/**
* Information provided to `executeAsync` by the `OperationExecutionManager`.
*
* @beta
*/
export interface IExecuteOperationContext extends Omit<IOperationRunnerContext, 'isFirstRun' | 'requestRun'> {
/**
* Function to invoke before execution of an operation, for logging.
*/
beforeExecute(operation: Operation, state: IOperationState): void;
/**
* Function to invoke after execution of an operation, for logging.
*/
afterExecute(operation: Operation, state: IOperationState): void;
/**
* Function used to schedule the concurrency-limited execution of an operation.
*
* Will return OperationStatus.Aborted if execution is aborted before the task executes.
*/
queueWork(workFn: () => Promise<OperationStatus>, priority: number): Promise<OperationStatus>;
/**
* A callback to the overarching orchestrator to request that the operation be invoked again.
* Used in watch mode to signal that inputs have changed.
*/
requestRun?: (requestor?: string) => void;
/**
* Terminal to write output to.
*/
terminal: ITerminal;
}
/**
* The `Operation` class is a node in the dependency graph of work that needs to be scheduled by the
* `OperationExecutionManager`. Each `Operation` has a `runner` member of type `IOperationRunner`, whose
* implementation manages the actual process of running a single operation.
*
* The graph of `Operation` instances will be cloned into a separate execution graph after processing.
*
* @beta
*/
export declare class Operation implements IOperationStates {
/**
* A set of all dependencies which must be executed before this operation is complete.
*/
readonly dependencies: Set<Operation>;
/**
* A set of all operations that wait for this operation.
*/
readonly consumers: Set<Operation>;
/**
* If specified, the name of a grouping to which this Operation belongs, for logging start and end times.
*/
readonly groupName: string | undefined;
/**
* The name of this operation, for logging.
*/
readonly name: string | undefined;
/**
* When the scheduler is ready to process this `Operation`, the `runner` implements the actual work of
* running the operation.
*/
runner: IOperationRunner | undefined;
/**
* This number represents how far away this Operation is from the furthest "root" operation (i.e.
* an operation with no consumers). This helps us to calculate the critical path (i.e. the
* longest chain of projects which must be executed in order, thereby limiting execution speed
* of the entire operation tree.
*
* This number is calculated via a memoized depth-first search, and when choosing the next
* operation to execute, the operation with the highest criticalPathLength is chosen.
*
* Example:
* (0) A
* \\
* (1) B C (0) (applications)
* \\ /|\\
* \\ / | \\
* (2) D | X (1) (utilities)
* | / \\
* |/ \\
* (2) Y Z (2) (other utilities)
*
* All roots (A & C) have a criticalPathLength of 0.
* B has a score of 1, since A depends on it.
* D has a score of 2, since we look at the longest chain (e.g D-\>B-\>A is longer than D-\>C)
* X has a score of 1, since the only package which depends on it is A
* Z has a score of 2, since only X depends on it, and X has a score of 1
* Y has a score of 2, since the chain Y-\>X-\>C is longer than Y-\>C
*
* The algorithm is implemented in AsyncOperationQueue.ts as calculateCriticalPathLength()
*/
criticalPathLength: number | undefined;
/**
* The weight for this operation. This scalar is the contribution of this operation to the
* `criticalPathLength` calculation above. Modify to indicate the following:
* - `weight` === 1: indicates that this operation has an average duration
* - `weight` > 1: indicates that this operation takes longer than average and so the scheduler
* should try to favor starting it over other, shorter operations. An example might be an operation that
* bundles an entire application and runs whole-program optimization.
* - `weight` < 1: indicates that this operation takes less time than average and so the scheduler
* should favor other, longer operations over it. An example might be an operation to unpack a cached
* output, or an operation using NullOperationRunner, which might use a value of 0.
*/
weight: number;
/**
* The state of this operation the previous time a manager was invoked.
*/
lastState: IOperationState | undefined;
/**
* The current state of this operation
*/
state: IOperationState | undefined;
/**
* A cached execution promise for the current OperationExecutionManager invocation of this operation.
*/
private _promise;
/**
* If true, then a run of this operation is currently wanted.
* This is used to track state from the `requestRun` callback passed to the runner.
*/
private _runPending;
constructor(options?: IOperationOptions);
addDependency(dependency: Operation): void;
deleteDependency(dependency: Operation): void;
reset(): void;
/**
* @internal
*/
_executeAsync(context: IExecuteOperationContext): Promise<OperationStatus>;
private _executeInnerAsync;
}
//# sourceMappingURL=Operation.d.ts.map