kist
Version:
Package Pipeline Processor
108 lines (107 loc) • 5.19 kB
JavaScript
;
// ============================================================================
// Import
// ============================================================================
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pipeline = void 0;
const AbstractProcess_1 = require("../abstract/AbstractProcess");
const Stage_1 = require("./Stage");
// ============================================================================
// Class
// ============================================================================
/**
* Represents the pipeline of stages to be executed.
* This class manages the execution flow of stages, including parallel
* execution, dependency handling, and applying global options for consistent
* pipeline behavior.
*/
class Pipeline extends AbstractProcess_1.AbstractProcess {
// Constructor
// ========================================================================
/**
* Constructs a new Pipeline instance with the given configuration.
* Initializes stages and applies global options for execution control.
*
* @param config - The configuration object defining the stages, steps,
* and global options for the pipeline.
*/
constructor(config) {
super();
this.config = config;
this.stages = config.stages.map((stage) => new Stage_1.Stage(stage));
this.options = config.options;
this.logInfo("Pipeline instance created.");
}
// Methods
// ========================================================================
/**
* Runs the pipeline, executing stages based on their dependencies.
* Stages are run in parallel by default, but their execution respects
* defined dependencies. Applies global options for logging, error
* handling, and execution control.
*/
run() {
return __awaiter(this, void 0, void 0, function* () {
var _a;
this.logInfo("Starting pipeline execution...");
// Track stages that have been completed
const completedStages = new Set();
// Run stages with dependency management and parallel execution control
try {
this.logDebug("Pipeline execution started with debug logging.");
// Execute all stages with concurrency control
const stagePromises = this.stages.map((stage) => stage.execute(completedStages));
yield this.runWithConcurrencyControl(stagePromises);
this.logInfo("Pipeline execution completed successfully.");
}
catch (error) {
this.logError("Pipeline execution failed:", error);
// Halt pipeline if configured to do so on failure
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.haltOnFailure) !== false) {
this.logError("Halting pipeline due to failure.");
process.exit(1);
}
else {
this.logWarn("Continuing pipeline execution despite errors.");
}
}
});
}
/**
* Runs the stage promises with concurrency control based on global
* options. Limits the number of parallel running stages if
* maxConcurrentStages is set in global options.
* @param stagePromises - An array of promises representing stage
* executions.
*/
runWithConcurrencyControl(stagePromises) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const maxConcurrentStages = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.maxConcurrentStages) || stagePromises.length;
// Process stages with a concurrency limit
const executingStages = new Set();
for (const stagePromise of stagePromises) {
executingStages.add(stagePromise);
// Ensure stages are removed from the set once complete
stagePromise.finally(() => executingStages.delete(stagePromise));
// Enforce concurrency limit
if (executingStages.size >= maxConcurrentStages) {
// Wait until at least one stage completes
yield Promise.race(executingStages);
}
}
// Wait for all remaining stages to complete
yield Promise.all(executingStages);
});
}
}
exports.Pipeline = Pipeline;