@calmo/task-runner 1.2.2 → 1.2.3
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/.gemini/commands/openspec/apply.toml +21 -0
- package/.gemini/commands/openspec/archive.toml +25 -0
- package/.gemini/commands/openspec/proposal.toml +26 -0
- package/AGENTS.md +18 -0
- package/CHANGELOG.md +16 -0
- package/GEMINI.md +8 -0
- package/coverage/coverage-final.json +4 -4
- package/coverage/index.html +9 -9
- package/coverage/lcov-report/index.html +9 -9
- package/coverage/lcov-report/src/EventBus.ts.html +4 -4
- package/coverage/lcov-report/src/TaskGraphValidator.ts.html +35 -5
- package/coverage/lcov-report/src/TaskRunner.ts.html +7 -109
- package/coverage/lcov-report/src/WorkflowExecutor.ts.html +166 -109
- package/coverage/lcov-report/src/contracts/RunnerEvents.ts.html +1 -1
- package/coverage/lcov-report/src/contracts/index.html +1 -1
- package/coverage/lcov-report/src/index.html +16 -16
- package/coverage/lcov.info +120 -144
- package/coverage/src/EventBus.ts.html +4 -4
- package/coverage/src/TaskGraphValidator.ts.html +35 -5
- package/coverage/src/TaskRunner.ts.html +7 -109
- package/coverage/src/WorkflowExecutor.ts.html +166 -109
- package/coverage/src/contracts/RunnerEvents.ts.html +1 -1
- package/coverage/src/contracts/index.html +1 -1
- package/coverage/src/index.html +16 -16
- package/dist/TaskGraphValidator.d.ts +6 -0
- package/dist/TaskGraphValidator.js +9 -0
- package/dist/TaskGraphValidator.js.map +1 -1
- package/dist/TaskRunner.js +1 -32
- package/dist/TaskRunner.js.map +1 -1
- package/dist/WorkflowExecutor.d.ts +9 -0
- package/dist/WorkflowExecutor.js +74 -54
- package/dist/WorkflowExecutor.js.map +1 -1
- package/dist/contracts/ITaskGraphValidator.d.ts +6 -0
- package/openspec/AGENTS.md +456 -0
- package/openspec/changes/add-external-task-cancellation/proposal.md +14 -0
- package/openspec/changes/add-external-task-cancellation/tasks.md +10 -0
- package/openspec/project.md +31 -0
- package/package.json +1 -1
- package/src/TaskGraphValidator.ts +10 -0
- package/src/TaskRunner.ts +1 -35
- package/src/WorkflowExecutor.ts +81 -62
- package/src/contracts/ITaskGraphValidator.ts +7 -0
- package/test-report.xml +47 -39
package/coverage/src/index.html
CHANGED
|
@@ -25,28 +25,28 @@
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
26
|
<span class="strong">100% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>121/121</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
33
|
<span class="strong">100% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>42/42</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
40
|
<span class="strong">100% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>19/19</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
47
|
<span class="strong">100% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>119/119</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -99,13 +99,13 @@
|
|
|
99
99
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
100
100
|
</td>
|
|
101
101
|
<td data-value="100" class="pct high">100%</td>
|
|
102
|
-
<td data-value="
|
|
102
|
+
<td data-value="46" class="abs high">46/46</td>
|
|
103
103
|
<td data-value="100" class="pct high">100%</td>
|
|
104
104
|
<td data-value="16" class="abs high">16/16</td>
|
|
105
105
|
<td data-value="100" class="pct high">100%</td>
|
|
106
|
-
<td data-value="
|
|
106
|
+
<td data-value="5" class="abs high">5/5</td>
|
|
107
107
|
<td data-value="100" class="pct high">100%</td>
|
|
108
|
-
<td data-value="
|
|
108
|
+
<td data-value="44" class="abs high">44/44</td>
|
|
109
109
|
</tr>
|
|
110
110
|
|
|
111
111
|
<tr>
|
|
@@ -114,13 +114,13 @@
|
|
|
114
114
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
115
115
|
</td>
|
|
116
116
|
<td data-value="100" class="pct high">100%</td>
|
|
117
|
-
<td data-value="
|
|
117
|
+
<td data-value="12" class="abs high">12/12</td>
|
|
118
118
|
<td data-value="100" class="pct high">100%</td>
|
|
119
|
-
<td data-value="
|
|
119
|
+
<td data-value="4" class="abs high">4/4</td>
|
|
120
120
|
<td data-value="100" class="pct high">100%</td>
|
|
121
|
-
<td data-value="
|
|
121
|
+
<td data-value="5" class="abs high">5/5</td>
|
|
122
122
|
<td data-value="100" class="pct high">100%</td>
|
|
123
|
-
<td data-value="
|
|
123
|
+
<td data-value="12" class="abs high">12/12</td>
|
|
124
124
|
</tr>
|
|
125
125
|
|
|
126
126
|
<tr>
|
|
@@ -129,13 +129,13 @@
|
|
|
129
129
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
130
130
|
</td>
|
|
131
131
|
<td data-value="100" class="pct high">100%</td>
|
|
132
|
-
<td data-value="
|
|
132
|
+
<td data-value="48" class="abs high">48/48</td>
|
|
133
133
|
<td data-value="100" class="pct high">100%</td>
|
|
134
|
-
<td data-value="
|
|
134
|
+
<td data-value="14" class="abs high">14/14</td>
|
|
135
135
|
<td data-value="100" class="pct high">100%</td>
|
|
136
|
-
<td data-value="
|
|
136
|
+
<td data-value="5" class="abs high">5/5</td>
|
|
137
137
|
<td data-value="100" class="pct high">100%</td>
|
|
138
|
-
<td data-value="
|
|
138
|
+
<td data-value="48" class="abs high">48/48</td>
|
|
139
139
|
</tr>
|
|
140
140
|
|
|
141
141
|
</tbody>
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
147
147
|
Code coverage generated by
|
|
148
148
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
149
|
-
at 2026-01-
|
|
149
|
+
at 2026-01-18T14:25:37.513Z
|
|
150
150
|
</div>
|
|
151
151
|
<script src="../prettify.js"></script>
|
|
152
152
|
<script>
|
|
@@ -13,5 +13,11 @@ export declare class TaskGraphValidator implements ITaskGraphValidator {
|
|
|
13
13
|
* @returns A ValidationResult object indicating the outcome of the validation.
|
|
14
14
|
*/
|
|
15
15
|
validate(taskGraph: TaskGraph): ValidationResult;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a human-readable error message from a validation result.
|
|
18
|
+
* @param result The validation result containing errors.
|
|
19
|
+
* @returns A formatted error string.
|
|
20
|
+
*/
|
|
21
|
+
createErrorMessage(result: ValidationResult): string;
|
|
16
22
|
private detectCycle;
|
|
17
23
|
}
|
|
@@ -78,6 +78,15 @@ export class TaskGraphValidator {
|
|
|
78
78
|
errors
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a human-readable error message from a validation result.
|
|
83
|
+
* @param result The validation result containing errors.
|
|
84
|
+
* @returns A formatted error string.
|
|
85
|
+
*/
|
|
86
|
+
createErrorMessage(result) {
|
|
87
|
+
const errorDetails = result.errors.map(e => e.message);
|
|
88
|
+
return `Task graph validation failed: ${errorDetails.join("; ")}`;
|
|
89
|
+
}
|
|
81
90
|
detectCycle(taskId, path, visited, recursionStack, adjacencyList) {
|
|
82
91
|
visited.add(taskId);
|
|
83
92
|
recursionStack.add(taskId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskGraphValidator.js","sourceRoot":"","sources":["../src/TaskGraphValidator.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TaskGraphValidator.js","sourceRoot":"","sources":["../src/TaskGraphValidator.ts"],"names":[],"mappings":"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"}
|
package/dist/TaskRunner.js
CHANGED
|
@@ -49,38 +49,7 @@ export class TaskRunner {
|
|
|
49
49
|
};
|
|
50
50
|
const validationResult = this.validator.validate(taskGraph);
|
|
51
51
|
if (!validationResult.isValid) {
|
|
52
|
-
|
|
53
|
-
const affectedTasks = new Set();
|
|
54
|
-
const errorDetails = [];
|
|
55
|
-
for (const error of validationResult.errors) {
|
|
56
|
-
errorDetails.push(error.message);
|
|
57
|
-
switch (error.type) {
|
|
58
|
-
case "cycle": {
|
|
59
|
-
// details is { cyclePath: string[] }
|
|
60
|
-
const path = error.details.cyclePath;
|
|
61
|
-
// The last element duplicates the first in the path representation, so valid unique tasks are slice(0, -1) or just all as Set handles uniq
|
|
62
|
-
path.forEach((t) => affectedTasks.add(t));
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
case "missing_dependency": {
|
|
66
|
-
// details is { taskId: string, missingDependencyId: string }
|
|
67
|
-
const d = error.details;
|
|
68
|
-
affectedTasks.add(d.taskId);
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
case "duplicate_task": {
|
|
72
|
-
const d = error.details;
|
|
73
|
-
affectedTasks.add(d.taskId);
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// Legacy error format: "Circular dependency or missing dependency detected. Unable to run tasks: A, B"
|
|
79
|
-
const taskList = Array.from(affectedTasks).join(", ");
|
|
80
|
-
const legacyMessage = `Circular dependency or missing dependency detected. Unable to run tasks: ${taskList}`;
|
|
81
|
-
const detailedMessage = `Task graph validation failed: ${errorDetails.join("; ")}`;
|
|
82
|
-
// Combine them to satisfy both legacy tests (checking for legacy message) and new requirements (clear details)
|
|
83
|
-
throw new Error(`${legacyMessage} | ${detailedMessage}`);
|
|
52
|
+
throw new Error(this.validator.createErrorMessage(validationResult));
|
|
84
53
|
}
|
|
85
54
|
const executor = new WorkflowExecutor(this.context, this.eventBus);
|
|
86
55
|
return executor.execute(steps);
|
package/dist/TaskRunner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskRunner.js","sourceRoot":"","sources":["../src/TaskRunner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKzD;;;;GAIG;AACH,MAAM,OAAO,UAAU;IAOD;IANZ,QAAQ,GAAG,IAAI,QAAQ,EAAY,CAAC;IACpC,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAE7C;;OAEG;IACH,YAAoB,OAAiB;QAAjB,YAAO,GAAP,OAAO,CAAU;IAAG,CAAC;IAEzC;;;;OAIG;IACI,EAAE,CACP,KAAQ,EACR,QAA0C;QAE1C,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACI,GAAG,CACR,KAAQ,EACR,QAA0C;QAE1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,KAA2B;QACvC,2CAA2C;QAC3C,MAAM,SAAS,GAAc;YAC3B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC1B,EAAE,EAAE,IAAI,CAAC,IAAI;gBACb,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;aACtC,CAAC,CAAC;SACJ,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC9B,
|
|
1
|
+
{"version":3,"file":"TaskRunner.js","sourceRoot":"","sources":["../src/TaskRunner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKzD;;;;GAIG;AACH,MAAM,OAAO,UAAU;IAOD;IANZ,QAAQ,GAAG,IAAI,QAAQ,EAAY,CAAC;IACpC,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAE7C;;OAEG;IACH,YAAoB,OAAiB;QAAjB,YAAO,GAAP,OAAO,CAAU;IAAG,CAAC;IAEzC;;;;OAIG;IACI,EAAE,CACP,KAAQ,EACR,QAA0C;QAE1C,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACI,GAAG,CACR,KAAQ,EACR,QAA0C;QAE1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,KAA2B;QACvC,2CAA2C;QAC3C,MAAM,SAAS,GAAc;YAC3B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC1B,EAAE,EAAE,IAAI,CAAC,IAAI;gBACb,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;aACtC,CAAC,CAAC;SACJ,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -20,4 +20,13 @@ export declare class WorkflowExecutor<TContext> {
|
|
|
20
20
|
* @returns A Promise that resolves to a map of task results.
|
|
21
21
|
*/
|
|
22
22
|
execute(steps: TaskStep<TContext>[]): Promise<Map<string, TaskResult>>;
|
|
23
|
+
/**
|
|
24
|
+
* Logic to identify tasks that can be started or must be skipped.
|
|
25
|
+
* Iterate only over pending steps to avoid O(N^2) checks on completed tasks.
|
|
26
|
+
*/
|
|
27
|
+
private processQueue;
|
|
28
|
+
/**
|
|
29
|
+
* Handles the lifecycle of a single task execution.
|
|
30
|
+
*/
|
|
31
|
+
private runStep;
|
|
23
32
|
}
|
package/dist/WorkflowExecutor.js
CHANGED
|
@@ -23,67 +23,87 @@ export class WorkflowExecutor {
|
|
|
23
23
|
this.eventBus.emit("workflowStart", { context: this.context, steps });
|
|
24
24
|
const results = new Map();
|
|
25
25
|
const executingPromises = new Set();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// 1. Identify and mark skipped tasks
|
|
30
|
-
for (const step of pendingSteps) {
|
|
31
|
-
const deps = step.dependencies ?? [];
|
|
32
|
-
const failedDep = deps.find((dep) => results.has(dep) && results.get(dep)?.status !== "success");
|
|
33
|
-
if (failedDep) {
|
|
34
|
-
const result = {
|
|
35
|
-
status: "skipped",
|
|
36
|
-
message: `Skipped due to failed dependency: ${failedDep}`,
|
|
37
|
-
};
|
|
38
|
-
results.set(step.name, result);
|
|
39
|
-
this.eventBus.emit("taskSkipped", { step, result });
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Re-filter pending steps as some might have been skipped above
|
|
43
|
-
const readySteps = steps.filter((step) => {
|
|
44
|
-
if (results.has(step.name) || this.running.has(step.name))
|
|
45
|
-
return false;
|
|
46
|
-
const deps = step.dependencies ?? [];
|
|
47
|
-
return deps.every((dep) => results.has(dep) && results.get(dep)?.status === "success");
|
|
48
|
-
});
|
|
49
|
-
// 2. Launch ready tasks
|
|
50
|
-
for (const step of readySteps) {
|
|
51
|
-
this.running.add(step.name);
|
|
52
|
-
this.eventBus.emit("taskStart", { step });
|
|
53
|
-
const taskPromise = (async () => {
|
|
54
|
-
try {
|
|
55
|
-
const result = await step.run(this.context);
|
|
56
|
-
results.set(step.name, result);
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
results.set(step.name, {
|
|
60
|
-
status: "failure",
|
|
61
|
-
error: e instanceof Error ? e.message : String(e),
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
finally {
|
|
65
|
-
this.running.delete(step.name);
|
|
66
|
-
const result = results.get(step.name);
|
|
67
|
-
this.eventBus.emit("taskEnd", { step, result });
|
|
68
|
-
}
|
|
69
|
-
})();
|
|
70
|
-
// Wrap the task promise to ensure we can track it in the Set
|
|
71
|
-
const trackedPromise = taskPromise.then(() => {
|
|
72
|
-
executingPromises.delete(trackedPromise);
|
|
73
|
-
});
|
|
74
|
-
executingPromises.add(trackedPromise);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
// Initial check to start independent tasks
|
|
78
|
-
processPendingSteps();
|
|
26
|
+
const pendingSteps = new Set(steps);
|
|
27
|
+
// Initial pass
|
|
28
|
+
this.processQueue(pendingSteps, results, executingPromises);
|
|
79
29
|
while (results.size < steps.length && executingPromises.size > 0) {
|
|
80
30
|
// Wait for the next task to finish
|
|
81
31
|
await Promise.race(executingPromises);
|
|
82
32
|
// After a task finishes, check for new work
|
|
83
|
-
|
|
33
|
+
this.processQueue(pendingSteps, results, executingPromises);
|
|
84
34
|
}
|
|
85
35
|
this.eventBus.emit("workflowEnd", { context: this.context, results });
|
|
86
36
|
return results;
|
|
87
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Logic to identify tasks that can be started or must be skipped.
|
|
40
|
+
* Iterate only over pending steps to avoid O(N^2) checks on completed tasks.
|
|
41
|
+
*/
|
|
42
|
+
processQueue(pendingSteps, results, executingPromises) {
|
|
43
|
+
const toRemove = [];
|
|
44
|
+
const toRun = [];
|
|
45
|
+
for (const step of pendingSteps) {
|
|
46
|
+
const deps = step.dependencies ?? [];
|
|
47
|
+
let blocked = false;
|
|
48
|
+
let failedDep;
|
|
49
|
+
for (const dep of deps) {
|
|
50
|
+
const depResult = results.get(dep);
|
|
51
|
+
if (!depResult) {
|
|
52
|
+
// Dependency not finished yet
|
|
53
|
+
blocked = true;
|
|
54
|
+
}
|
|
55
|
+
else if (depResult.status !== "success") {
|
|
56
|
+
failedDep = dep;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (failedDep) {
|
|
61
|
+
const result = {
|
|
62
|
+
status: "skipped",
|
|
63
|
+
message: `Skipped due to failed dependency: ${failedDep}`,
|
|
64
|
+
};
|
|
65
|
+
results.set(step.name, result);
|
|
66
|
+
this.eventBus.emit("taskSkipped", { step, result });
|
|
67
|
+
toRemove.push(step);
|
|
68
|
+
}
|
|
69
|
+
else if (!blocked) {
|
|
70
|
+
toRun.push(step);
|
|
71
|
+
toRemove.push(step);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Cleanup pending set
|
|
75
|
+
for (const step of toRemove) {
|
|
76
|
+
pendingSteps.delete(step);
|
|
77
|
+
}
|
|
78
|
+
// Execute ready tasks
|
|
79
|
+
for (const step of toRun) {
|
|
80
|
+
const taskPromise = this.runStep(step, results).then(() => {
|
|
81
|
+
executingPromises.delete(taskPromise);
|
|
82
|
+
});
|
|
83
|
+
executingPromises.add(taskPromise);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handles the lifecycle of a single task execution.
|
|
88
|
+
*/
|
|
89
|
+
async runStep(step, results) {
|
|
90
|
+
this.running.add(step.name);
|
|
91
|
+
this.eventBus.emit("taskStart", { step });
|
|
92
|
+
try {
|
|
93
|
+
const result = await step.run(this.context);
|
|
94
|
+
results.set(step.name, result);
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
results.set(step.name, {
|
|
98
|
+
status: "failure",
|
|
99
|
+
error: e instanceof Error ? e.message : String(e),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
this.running.delete(step.name);
|
|
104
|
+
const result = results.get(step.name);
|
|
105
|
+
this.eventBus.emit("taskEnd", { step, result });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
88
108
|
}
|
|
89
109
|
//# sourceMappingURL=WorkflowExecutor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowExecutor.js","sourceRoot":"","sources":["../src/WorkflowExecutor.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IAQjB;IACA;IARF,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC;;;OAGG;IACH,YACU,OAAiB,EACjB,QAA4B;QAD5B,YAAO,GAAP,OAAO,CAAU;QACjB,aAAQ,GAAR,QAAQ,CAAoB;IACnC,CAAC;IAEJ;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,KAA2B;QACvC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEtE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC9C,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkflowExecutor.js","sourceRoot":"","sources":["../src/WorkflowExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,4 +10,10 @@ export interface ITaskGraphValidator {
|
|
|
10
10
|
* @returns A ValidationResult object indicating the outcome of the validation.
|
|
11
11
|
*/
|
|
12
12
|
validate(taskGraph: TaskGraph): ValidationResult;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a human-readable error message from a validation result.
|
|
15
|
+
* @param result The validation result containing errors.
|
|
16
|
+
* @returns A formatted error string.
|
|
17
|
+
*/
|
|
18
|
+
createErrorMessage(result: ValidationResult): string;
|
|
13
19
|
}
|