@eldrforge/tree-execution 0.1.0
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/LICENSE +22 -0
- package/README.md +130 -0
- package/dist/TreeExecutor.d.ts +113 -0
- package/dist/TreeExecutor.d.ts.map +1 -0
- package/dist/TreeExecutor.js +113 -0
- package/dist/TreeExecutor.js.map +1 -0
- package/dist/checkpoint/CheckpointManager.d.ts +18 -0
- package/dist/checkpoint/CheckpointManager.d.ts.map +1 -0
- package/dist/checkpoint/CheckpointManager.js +156 -0
- package/dist/checkpoint/CheckpointManager.js.map +1 -0
- package/dist/checkpoint/index.d.ts +5 -0
- package/dist/checkpoint/index.d.ts.map +1 -0
- package/dist/checkpoint/index.js +5 -0
- package/dist/checkpoint/index.js.map +1 -0
- package/dist/execution/CommandValidator.d.ts +25 -0
- package/dist/execution/CommandValidator.d.ts.map +1 -0
- package/dist/execution/CommandValidator.js +129 -0
- package/dist/execution/CommandValidator.js.map +1 -0
- package/dist/execution/DependencyChecker.d.ts +47 -0
- package/dist/execution/DependencyChecker.d.ts.map +1 -0
- package/dist/execution/DependencyChecker.js +95 -0
- package/dist/execution/DependencyChecker.js.map +1 -0
- package/dist/execution/DynamicTaskPool.d.ts +118 -0
- package/dist/execution/DynamicTaskPool.d.ts.map +1 -0
- package/dist/execution/DynamicTaskPool.js +658 -0
- package/dist/execution/DynamicTaskPool.js.map +1 -0
- package/dist/execution/RecoveryManager.d.ts +89 -0
- package/dist/execution/RecoveryManager.d.ts.map +1 -0
- package/dist/execution/RecoveryManager.js +592 -0
- package/dist/execution/RecoveryManager.js.map +1 -0
- package/dist/execution/ResourceMonitor.d.ts +73 -0
- package/dist/execution/ResourceMonitor.d.ts.map +1 -0
- package/dist/execution/ResourceMonitor.js +148 -0
- package/dist/execution/ResourceMonitor.js.map +1 -0
- package/dist/execution/Scheduler.d.ts +36 -0
- package/dist/execution/Scheduler.d.ts.map +1 -0
- package/dist/execution/Scheduler.js +83 -0
- package/dist/execution/Scheduler.js.map +1 -0
- package/dist/execution/TreeExecutionAdapter.d.ts +45 -0
- package/dist/execution/TreeExecutionAdapter.d.ts.map +1 -0
- package/dist/execution/TreeExecutionAdapter.js +249 -0
- package/dist/execution/TreeExecutionAdapter.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/tree.d.ts +13 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +2453 -0
- package/dist/tree.js.map +1 -0
- package/dist/types/config.d.ts +172 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/parallelExecution.d.ts +108 -0
- package/dist/types/parallelExecution.d.ts.map +1 -0
- package/dist/types/parallelExecution.js +2 -0
- package/dist/types/parallelExecution.js.map +1 -0
- package/dist/util/commandStubs.d.ts +22 -0
- package/dist/util/commandStubs.d.ts.map +1 -0
- package/dist/util/commandStubs.js +49 -0
- package/dist/util/commandStubs.js.map +1 -0
- package/dist/util/logger.d.ts +14 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +15 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/mutex.d.ts +38 -0
- package/dist/util/mutex.d.ts.map +1 -0
- package/dist/util/mutex.js +101 -0
- package/dist/util/mutex.js.map +1 -0
- package/dist/util/treeUtils.d.ts +46 -0
- package/dist/util/treeUtils.d.ts.map +1 -0
- package/dist/util/treeUtils.js +74 -0
- package/dist/util/treeUtils.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { getLogger } from '../util/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* CommandValidator checks if commands are safe for parallel execution
|
|
4
|
+
*/
|
|
5
|
+
export class CommandValidator {
|
|
6
|
+
static logger = getLogger();
|
|
7
|
+
/**
|
|
8
|
+
* Validate a command for parallel execution
|
|
9
|
+
*/
|
|
10
|
+
static validateForParallel(command, builtInCommand) {
|
|
11
|
+
const issues = [];
|
|
12
|
+
const warnings = [];
|
|
13
|
+
const recommendations = [];
|
|
14
|
+
// Check for inherently unsafe operations
|
|
15
|
+
const unsafePatterns = [
|
|
16
|
+
{ pattern: /git\s+checkout/, message: 'Branch switching is not safe for parallel execution' },
|
|
17
|
+
{ pattern: /git\s+switch/, message: 'Branch switching is not safe for parallel execution' },
|
|
18
|
+
{ pattern: /git\s+rebase/, message: 'Rebase operations should not run in parallel' },
|
|
19
|
+
{ pattern: /git\s+merge/, message: 'Merge operations should not run in parallel' },
|
|
20
|
+
{ pattern: /rm\s+-rf\s+\//, message: 'Dangerous deletion commands detected' },
|
|
21
|
+
{ pattern: /sudo/, message: 'Sudo commands should not run in parallel' },
|
|
22
|
+
{ pattern: /format/, message: 'Format commands may be destructive' }
|
|
23
|
+
];
|
|
24
|
+
for (const { pattern, message } of unsafePatterns) {
|
|
25
|
+
if (pattern.test(command)) {
|
|
26
|
+
issues.push(message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Check for potentially problematic operations
|
|
30
|
+
const warningPatterns = [
|
|
31
|
+
{ pattern: /npm\s+(link|unlink)/, message: 'npm link/unlink may conflict in parallel execution' },
|
|
32
|
+
{ pattern: /npm\s+install/, message: 'npm install in parallel may cause lock file conflicts' },
|
|
33
|
+
{ pattern: /npm\s+ci/, message: 'npm ci in parallel may cause lock file conflicts' },
|
|
34
|
+
{ pattern: /package-lock\.json/, message: 'Operations modifying package-lock.json may conflict' },
|
|
35
|
+
{ pattern: /node_modules/, message: 'Operations in node_modules may conflict' }
|
|
36
|
+
];
|
|
37
|
+
for (const { pattern, message } of warningPatterns) {
|
|
38
|
+
if (pattern.test(command)) {
|
|
39
|
+
warnings.push(message);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Built-in command specific checks
|
|
43
|
+
if (builtInCommand === 'commit') {
|
|
44
|
+
warnings.push('Parallel commits: Recommend max concurrency of 2 to avoid conflicts');
|
|
45
|
+
recommendations.push('Use: --max-concurrency 2');
|
|
46
|
+
}
|
|
47
|
+
if (builtInCommand === 'publish') {
|
|
48
|
+
warnings.push('Parallel publish: PR checks may take significant time');
|
|
49
|
+
warnings.push('Version propagation happens automatically between dependency levels');
|
|
50
|
+
recommendations.push('Use: --max-concurrency 2-3 for publish operations');
|
|
51
|
+
recommendations.push('Monitor with: kodrdriv tree --status-parallel');
|
|
52
|
+
}
|
|
53
|
+
if (builtInCommand === 'link' || builtInCommand === 'unlink') {
|
|
54
|
+
warnings.push('Link operations may have filesystem race conditions');
|
|
55
|
+
recommendations.push('Consider sequential execution for link/unlink');
|
|
56
|
+
}
|
|
57
|
+
// Check for output redirection
|
|
58
|
+
if (command.includes('>') || command.includes('>>')) {
|
|
59
|
+
warnings.push('Output redirection in parallel may interleave output');
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
valid: issues.length === 0,
|
|
63
|
+
issues,
|
|
64
|
+
warnings,
|
|
65
|
+
recommendations
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Log validation results
|
|
70
|
+
*/
|
|
71
|
+
static logValidation(result) {
|
|
72
|
+
if (!result.valid) {
|
|
73
|
+
this.logger.error('VALIDATOR_FAILED: Command validation failed for parallel execution | Error Count: ' + result.issues.length + ' | Impact: Cannot proceed safely');
|
|
74
|
+
for (const issue of result.issues) {
|
|
75
|
+
this.logger.error(`VALIDATOR_ERROR_DETAIL: Validation issue | Issue: ${issue}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (result.warnings.length > 0) {
|
|
79
|
+
this.logger.warn('VALIDATOR_WARNINGS: Command validation warnings for parallel execution | Warning Count: ' + result.warnings.length + ' | Impact: May cause issues');
|
|
80
|
+
for (const warning of result.warnings) {
|
|
81
|
+
this.logger.warn(`VALIDATOR_WARNING_DETAIL: Validation warning | Warning: ${warning}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (result.recommendations.length > 0 && this.logger.verbose) {
|
|
85
|
+
this.logger.info('VALIDATOR_RECOMMENDATIONS: Command validation recommendations | Count: ' + result.recommendations.length + ' | Purpose: Improve parallel execution');
|
|
86
|
+
for (const rec of result.recommendations) {
|
|
87
|
+
this.logger.info(`VALIDATOR_RECOMMENDATION_DETAIL: ${rec}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get recommended concurrency for a command type
|
|
93
|
+
*/
|
|
94
|
+
static getRecommendedConcurrency(builtInCommand, cpuCount = 4, command) {
|
|
95
|
+
// If command is provided, check for memory-intensive patterns
|
|
96
|
+
if (command) {
|
|
97
|
+
const memoryIntensivePatterns = [
|
|
98
|
+
{ pattern: /npm\s+test/, message: 'Test execution is memory intensive' },
|
|
99
|
+
{ pattern: /npm\s+run\s+test/, message: 'Test execution is memory intensive' },
|
|
100
|
+
{ pattern: /vitest/, message: 'Vitest execution is memory intensive' },
|
|
101
|
+
{ pattern: /coverage/, message: 'Coverage generation is memory intensive' },
|
|
102
|
+
{ pattern: /npm\s+run\s+precommit/, message: 'Precommit tasks (build+lint+test) are resource intensive' }
|
|
103
|
+
];
|
|
104
|
+
for (const { pattern } of memoryIntensivePatterns) {
|
|
105
|
+
if (pattern.test(command)) {
|
|
106
|
+
// Return lower concurrency for memory intensive tasks: 25% of CPUs, min 2, max 4
|
|
107
|
+
const recommended = Math.max(2, Math.min(4, Math.floor(cpuCount * 0.25)));
|
|
108
|
+
return Math.min(recommended, cpuCount);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
switch (builtInCommand) {
|
|
113
|
+
case 'commit':
|
|
114
|
+
// Lower concurrency for commit to reduce conflicts
|
|
115
|
+
return Math.min(2, cpuCount);
|
|
116
|
+
case 'publish':
|
|
117
|
+
// Moderate concurrency for publish (long-running)
|
|
118
|
+
return Math.max(2, Math.floor(cpuCount / 2));
|
|
119
|
+
case 'link':
|
|
120
|
+
case 'unlink':
|
|
121
|
+
// Very conservative for link operations
|
|
122
|
+
return 1; // Sequential recommended
|
|
123
|
+
default:
|
|
124
|
+
// Full concurrency for general commands
|
|
125
|
+
return cpuCount;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=CommandValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandValidator.js","sourceRoot":"","sources":["../../src/execution/CommandValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { DependencyGraph } from '@eldrforge/tree-core';
|
|
2
|
+
import type { ExecutionState } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* DependencyChecker validates package readiness and provides dependency information
|
|
5
|
+
* for the task pool scheduler.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DependencyChecker {
|
|
8
|
+
private graph;
|
|
9
|
+
constructor(graph: DependencyGraph);
|
|
10
|
+
/**
|
|
11
|
+
* Check if a package is ready to execute
|
|
12
|
+
* A package is ready when all its dependencies are completed and none have failed
|
|
13
|
+
*/
|
|
14
|
+
isReady(packageName: string, state: ExecutionState): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Get count of packages that depend on this one
|
|
17
|
+
* Higher count = higher priority (unlocks more packages)
|
|
18
|
+
*/
|
|
19
|
+
getDependentCount(packageName: string): number;
|
|
20
|
+
/**
|
|
21
|
+
* Get depth of package in dependency tree
|
|
22
|
+
* Depth = longest path from a root package (package with no dependencies)
|
|
23
|
+
* Lower depth = higher priority (can unlock dependent packages sooner)
|
|
24
|
+
*/
|
|
25
|
+
getDepth(packageName: string): number;
|
|
26
|
+
/**
|
|
27
|
+
* Get all dependencies for a package
|
|
28
|
+
*/
|
|
29
|
+
getDependencies(packageName: string): Set<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Get all dependents (packages that depend on this one)
|
|
32
|
+
*/
|
|
33
|
+
getDependents(packageName: string): Set<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if package has any dependencies
|
|
36
|
+
*/
|
|
37
|
+
hasDependencies(packageName: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Check if package has any dependents
|
|
40
|
+
*/
|
|
41
|
+
hasDependents(packageName: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Get packages that are blocked by a failed package
|
|
44
|
+
*/
|
|
45
|
+
getBlockedPackages(failedPackage: string, state: ExecutionState): Set<string>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=DependencyChecker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DependencyChecker.d.ts","sourceRoot":"","sources":["../../src/execution/DependencyChecker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;GAGG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,KAAK,CAAkB;gBAEnB,KAAK,EAAE,eAAe;IAIlC;;;OAGG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO;IAkB5D;;;OAGG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAI9C;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAgBrC;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAIjD;;OAEG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAI/C;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAK7C;;OAEG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAK3C;;OAEG;IACH,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC;CAehF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DependencyChecker validates package readiness and provides dependency information
|
|
3
|
+
* for the task pool scheduler.
|
|
4
|
+
*/
|
|
5
|
+
export class DependencyChecker {
|
|
6
|
+
graph;
|
|
7
|
+
constructor(graph) {
|
|
8
|
+
this.graph = graph;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Check if a package is ready to execute
|
|
12
|
+
* A package is ready when all its dependencies are completed and none have failed
|
|
13
|
+
*/
|
|
14
|
+
isReady(packageName, state) {
|
|
15
|
+
const dependencies = this.graph.edges.get(packageName) || new Set();
|
|
16
|
+
for (const dep of dependencies) {
|
|
17
|
+
// If any dependency is not completed, not ready
|
|
18
|
+
if (!state.completed.includes(dep)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// If any dependency failed, should be skipped (not ready)
|
|
22
|
+
if (state.failed.some(f => f.name === dep)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get count of packages that depend on this one
|
|
30
|
+
* Higher count = higher priority (unlocks more packages)
|
|
31
|
+
*/
|
|
32
|
+
getDependentCount(packageName) {
|
|
33
|
+
return (this.graph.reverseEdges.get(packageName) || new Set()).size;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get depth of package in dependency tree
|
|
37
|
+
* Depth = longest path from a root package (package with no dependencies)
|
|
38
|
+
* Lower depth = higher priority (can unlock dependent packages sooner)
|
|
39
|
+
*/
|
|
40
|
+
getDepth(packageName) {
|
|
41
|
+
const visited = new Set();
|
|
42
|
+
const calculateDepth = (pkg) => {
|
|
43
|
+
if (visited.has(pkg))
|
|
44
|
+
return 0;
|
|
45
|
+
visited.add(pkg);
|
|
46
|
+
const deps = this.graph.edges.get(pkg) || new Set();
|
|
47
|
+
if (deps.size === 0)
|
|
48
|
+
return 0;
|
|
49
|
+
return 1 + Math.max(...Array.from(deps).map(dep => calculateDepth(dep)));
|
|
50
|
+
};
|
|
51
|
+
return calculateDepth(packageName);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get all dependencies for a package
|
|
55
|
+
*/
|
|
56
|
+
getDependencies(packageName) {
|
|
57
|
+
return this.graph.edges.get(packageName) || new Set();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get all dependents (packages that depend on this one)
|
|
61
|
+
*/
|
|
62
|
+
getDependents(packageName) {
|
|
63
|
+
return this.graph.reverseEdges.get(packageName) || new Set();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if package has any dependencies
|
|
67
|
+
*/
|
|
68
|
+
hasDependencies(packageName) {
|
|
69
|
+
const deps = this.graph.edges.get(packageName);
|
|
70
|
+
return deps !== undefined && deps.size > 0;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if package has any dependents
|
|
74
|
+
*/
|
|
75
|
+
hasDependents(packageName) {
|
|
76
|
+
const dependents = this.graph.reverseEdges.get(packageName);
|
|
77
|
+
return dependents !== undefined && dependents.size > 0;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get packages that are blocked by a failed package
|
|
81
|
+
*/
|
|
82
|
+
getBlockedPackages(failedPackage, state) {
|
|
83
|
+
const blocked = new Set();
|
|
84
|
+
// Add all pending and ready packages that depend on the failed package
|
|
85
|
+
const allPending = [...state.pending, ...state.ready];
|
|
86
|
+
for (const pkg of allPending) {
|
|
87
|
+
const deps = this.graph.edges.get(pkg) || new Set();
|
|
88
|
+
if (deps.has(failedPackage)) {
|
|
89
|
+
blocked.add(pkg);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return blocked;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=DependencyChecker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DependencyChecker.js","sourceRoot":"","sources":["../../src/execution/DependencyChecker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import type { TreeExecutionConfig } from '../types/config.js';
|
|
3
|
+
import type { DependencyGraph } from '@eldrforge/tree-core';
|
|
4
|
+
import type { ExecutionResult } from '../types/index.js';
|
|
5
|
+
export interface PoolConfig {
|
|
6
|
+
graph: DependencyGraph;
|
|
7
|
+
maxConcurrency: number;
|
|
8
|
+
command: string;
|
|
9
|
+
config: TreeExecutionConfig;
|
|
10
|
+
checkpointPath?: string;
|
|
11
|
+
continue?: boolean;
|
|
12
|
+
maxRetries?: number;
|
|
13
|
+
initialRetryDelay?: number;
|
|
14
|
+
maxRetryDelay?: number;
|
|
15
|
+
backoffMultiplier?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* DynamicTaskPool manages parallel execution of packages with dependency awareness
|
|
19
|
+
*/
|
|
20
|
+
export declare class DynamicTaskPool extends EventEmitter {
|
|
21
|
+
private config;
|
|
22
|
+
private graph;
|
|
23
|
+
private state;
|
|
24
|
+
private dependencyChecker;
|
|
25
|
+
private resourceMonitor;
|
|
26
|
+
private scheduler;
|
|
27
|
+
private checkpointManager;
|
|
28
|
+
private logger;
|
|
29
|
+
private executionId;
|
|
30
|
+
private startTime;
|
|
31
|
+
private runningTasks;
|
|
32
|
+
private packageStartTimes;
|
|
33
|
+
private packageEndTimes;
|
|
34
|
+
private packageDurations;
|
|
35
|
+
private retryAttempts;
|
|
36
|
+
private publishedVersions;
|
|
37
|
+
constructor(config: PoolConfig);
|
|
38
|
+
/**
|
|
39
|
+
* Main execution entry point
|
|
40
|
+
*/
|
|
41
|
+
execute(): Promise<ExecutionResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Initialize execution state
|
|
44
|
+
*/
|
|
45
|
+
private initializeState;
|
|
46
|
+
/**
|
|
47
|
+
* Schedule a package for execution
|
|
48
|
+
*/
|
|
49
|
+
private schedulePackage;
|
|
50
|
+
/**
|
|
51
|
+
* Execute a single package (placeholder - will be overridden or use callback)
|
|
52
|
+
*/
|
|
53
|
+
private executePackage;
|
|
54
|
+
/**
|
|
55
|
+
* Wait for next task to complete
|
|
56
|
+
*/
|
|
57
|
+
private waitForNext;
|
|
58
|
+
/**
|
|
59
|
+
* Handle task completion
|
|
60
|
+
*/
|
|
61
|
+
private handleTaskCompletion;
|
|
62
|
+
/**
|
|
63
|
+
* Handle successful package completion
|
|
64
|
+
*/
|
|
65
|
+
private handleSuccess;
|
|
66
|
+
/**
|
|
67
|
+
* Handle package failure
|
|
68
|
+
*/
|
|
69
|
+
private handleFailure;
|
|
70
|
+
/**
|
|
71
|
+
* Cascade failure to dependent packages
|
|
72
|
+
*/
|
|
73
|
+
private cascadeFailure;
|
|
74
|
+
/**
|
|
75
|
+
* Update ready queue
|
|
76
|
+
*/
|
|
77
|
+
private updateReadyQueue;
|
|
78
|
+
/**
|
|
79
|
+
* Check if execution is complete
|
|
80
|
+
*/
|
|
81
|
+
private isComplete;
|
|
82
|
+
/**
|
|
83
|
+
* Determine if should save checkpoint
|
|
84
|
+
*/
|
|
85
|
+
private shouldCheckpoint;
|
|
86
|
+
/**
|
|
87
|
+
* Save checkpoint
|
|
88
|
+
*/
|
|
89
|
+
private saveCheckpoint;
|
|
90
|
+
/**
|
|
91
|
+
* Load checkpoint
|
|
92
|
+
*/
|
|
93
|
+
private loadCheckpoint;
|
|
94
|
+
/**
|
|
95
|
+
* Build execution result
|
|
96
|
+
*/
|
|
97
|
+
private buildExecutionResult;
|
|
98
|
+
/**
|
|
99
|
+
* Check if error is retriable
|
|
100
|
+
*/
|
|
101
|
+
private isRetriableError;
|
|
102
|
+
/**
|
|
103
|
+
* Calculate retry delay with exponential backoff
|
|
104
|
+
*/
|
|
105
|
+
private calculateRetryDelay;
|
|
106
|
+
/**
|
|
107
|
+
* Format duration in human-readable format
|
|
108
|
+
*/
|
|
109
|
+
private formatDuration;
|
|
110
|
+
/**
|
|
111
|
+
* Extract detailed error information from error message and stack
|
|
112
|
+
*/
|
|
113
|
+
private extractErrorDetails;
|
|
114
|
+
private extractFirstErrorLine;
|
|
115
|
+
private getPackagePath;
|
|
116
|
+
private getLogFilePath;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=DynamicTaskPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicTaskPool.d.ts","sourceRoot":"","sources":["../../src/execution/DynamicTaskPool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,KAAK,EAGR,eAAe,EAIlB,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,eAAe,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAeD;;GAEG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC7C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAAe;IAG7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,iBAAiB,CAA0D;gBAEvE,MAAM,EAAE,UAAU;IAmB9B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAoEzC;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;OAEG;YACW,eAAe;IA2C7B;;OAEG;YACW,cAAc;IAS5B;;OAEG;YACW,WAAW;IAYzB;;OAEG;YACW,oBAAoB;IAuBlC;;OAEG;YACW,aAAa;IAwB3B;;OAEG;YACW,aAAa;IAkD3B;;OAEG;YACW,cAAc;IAoB5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;OAEG;IACH,OAAO,CAAC,UAAU;IAQlB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;YACW,cAAc;IAsD5B;;OAEG;YACW,cAAc;IAwE5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAyB5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmExB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwH3B,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,cAAc;CAOzB"}
|