@calmo/task-runner 3.8.0 → 3.8.1
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.md +6 -0
- package/coverage/coverage-final.json +5 -4
- package/coverage/index.html +18 -18
- package/coverage/lcov-report/index.html +18 -18
- package/coverage/lcov-report/src/EventBus.ts.html +4 -4
- package/coverage/lcov-report/src/TaskGraphValidationError.ts.html +1 -1
- package/coverage/lcov-report/src/TaskGraphValidator.ts.html +120 -60
- package/coverage/lcov-report/src/TaskRunner.ts.html +78 -63
- package/coverage/lcov-report/src/TaskRunnerBuilder.ts.html +1 -1
- package/coverage/lcov-report/src/TaskRunnerExecutionConfig.ts.html +1 -1
- package/coverage/lcov-report/src/TaskStateManager.ts.html +17 -29
- package/coverage/lcov-report/src/WorkflowExecutor.ts.html +1 -1
- package/coverage/lcov-report/src/contracts/ErrorTypes.ts.html +103 -0
- package/coverage/lcov-report/src/contracts/RunnerEvents.ts.html +1 -1
- package/coverage/lcov-report/src/contracts/index.html +23 -8
- package/coverage/lcov-report/src/index.html +10 -10
- package/coverage/lcov-report/src/strategies/DryRunExecutionStrategy.ts.html +1 -1
- package/coverage/lcov-report/src/strategies/RetryingExecutionStrategy.ts.html +1 -1
- package/coverage/lcov-report/src/strategies/StandardExecutionStrategy.ts.html +1 -1
- package/coverage/lcov-report/src/strategies/index.html +1 -1
- package/coverage/lcov.info +206 -184
- package/coverage/src/EventBus.ts.html +4 -4
- package/coverage/src/TaskGraphValidationError.ts.html +1 -1
- package/coverage/src/TaskGraphValidator.ts.html +120 -60
- package/coverage/src/TaskRunner.ts.html +78 -63
- package/coverage/src/TaskRunnerBuilder.ts.html +1 -1
- package/coverage/src/TaskRunnerExecutionConfig.ts.html +1 -1
- package/coverage/src/TaskStateManager.ts.html +17 -29
- package/coverage/src/WorkflowExecutor.ts.html +1 -1
- package/coverage/src/contracts/ErrorTypes.ts.html +103 -0
- package/coverage/src/contracts/RunnerEvents.ts.html +1 -1
- package/coverage/src/contracts/index.html +23 -8
- package/coverage/src/index.html +10 -10
- package/coverage/src/strategies/DryRunExecutionStrategy.ts.html +1 -1
- package/coverage/src/strategies/RetryingExecutionStrategy.ts.html +1 -1
- package/coverage/src/strategies/StandardExecutionStrategy.ts.html +1 -1
- package/coverage/src/strategies/index.html +1 -1
- package/dist/TaskGraphValidator.d.ts +3 -0
- package/dist/TaskGraphValidator.js +33 -26
- package/dist/TaskGraphValidator.js.map +1 -1
- package/dist/TaskRunner.d.ts +4 -0
- package/dist/TaskRunner.js +38 -44
- package/dist/TaskRunner.js.map +1 -1
- package/dist/TaskStateManager.js +1 -5
- package/dist/TaskStateManager.js.map +1 -1
- package/dist/contracts/ErrorTypes.d.ts +6 -0
- package/dist/contracts/ErrorTypes.js +7 -0
- package/dist/contracts/ErrorTypes.js.map +1 -0
- package/dist/contracts/ValidationError.d.ts +2 -1
- package/package.json +1 -1
- package/src/TaskGraphValidator.ts +52 -32
- package/src/TaskRunner.ts +51 -46
- package/src/TaskStateManager.ts +1 -5
- package/src/contracts/ErrorTypes.ts +6 -0
- package/src/contracts/ValidationError.ts +10 -1
- package/test-report.xml +134 -128
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
<span class="cline-any cline-neutral"> </span>
|
|
161
161
|
<span class="cline-any cline-neutral"> </span>
|
|
162
162
|
<span class="cline-any cline-neutral"> </span>
|
|
163
|
-
<span class="cline-any cline-yes">
|
|
163
|
+
<span class="cline-any cline-yes">81x</span>
|
|
164
164
|
<span class="cline-any cline-neutral"> </span>
|
|
165
165
|
<span class="cline-any cline-neutral"> </span>
|
|
166
166
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -207,10 +207,10 @@
|
|
|
207
207
|
<span class="cline-any cline-neutral"> </span>
|
|
208
208
|
<span class="cline-any cline-neutral"> </span>
|
|
209
209
|
<span class="cline-any cline-neutral"> </span>
|
|
210
|
-
<span class="cline-any cline-yes">
|
|
210
|
+
<span class="cline-any cline-yes">437x</span>
|
|
211
211
|
<span class="cline-any cline-neutral"> </span>
|
|
212
212
|
<span class="cline-any cline-neutral"> </span>
|
|
213
|
-
<span class="cline-any cline-yes">
|
|
213
|
+
<span class="cline-any cline-yes">437x</span>
|
|
214
214
|
<span class="cline-any cline-yes">14x</span>
|
|
215
215
|
<span class="cline-any cline-yes">14x</span>
|
|
216
216
|
<span class="cline-any cline-yes">14x</span>
|
|
@@ -328,7 +328,7 @@ export class EventBus<TContext> {
|
|
|
328
328
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
329
329
|
Code coverage generated by
|
|
330
330
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
331
|
-
at 2026-01-
|
|
331
|
+
at 2026-01-21T01:05:21.402Z
|
|
332
332
|
</div>
|
|
333
333
|
<script src="../prettify.js"></script>
|
|
334
334
|
<script>
|
|
@@ -115,7 +115,7 @@ export class TaskGraphValidationError extends Error {
|
|
|
115
115
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
116
116
|
Code coverage generated by
|
|
117
117
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
118
|
-
at 2026-01-
|
|
118
|
+
at 2026-01-21T01:05:21.402Z
|
|
119
119
|
</div>
|
|
120
120
|
<script src="../prettify.js"></script>
|
|
121
121
|
<script>
|
|
@@ -25,7 +25,7 @@
|
|
|
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'>59/59</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
@@ -39,14 +39,14 @@
|
|
|
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'>8/8</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'>58/58</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -231,7 +231,32 @@
|
|
|
231
231
|
<a name='L166'></a><a href='#L166'>166</a>
|
|
232
232
|
<a name='L167'></a><a href='#L167'>167</a>
|
|
233
233
|
<a name='L168'></a><a href='#L168'>168</a>
|
|
234
|
-
<a name='L169'></a><a href='#L169'>169</a
|
|
234
|
+
<a name='L169'></a><a href='#L169'>169</a>
|
|
235
|
+
<a name='L170'></a><a href='#L170'>170</a>
|
|
236
|
+
<a name='L171'></a><a href='#L171'>171</a>
|
|
237
|
+
<a name='L172'></a><a href='#L172'>172</a>
|
|
238
|
+
<a name='L173'></a><a href='#L173'>173</a>
|
|
239
|
+
<a name='L174'></a><a href='#L174'>174</a>
|
|
240
|
+
<a name='L175'></a><a href='#L175'>175</a>
|
|
241
|
+
<a name='L176'></a><a href='#L176'>176</a>
|
|
242
|
+
<a name='L177'></a><a href='#L177'>177</a>
|
|
243
|
+
<a name='L178'></a><a href='#L178'>178</a>
|
|
244
|
+
<a name='L179'></a><a href='#L179'>179</a>
|
|
245
|
+
<a name='L180'></a><a href='#L180'>180</a>
|
|
246
|
+
<a name='L181'></a><a href='#L181'>181</a>
|
|
247
|
+
<a name='L182'></a><a href='#L182'>182</a>
|
|
248
|
+
<a name='L183'></a><a href='#L183'>183</a>
|
|
249
|
+
<a name='L184'></a><a href='#L184'>184</a>
|
|
250
|
+
<a name='L185'></a><a href='#L185'>185</a>
|
|
251
|
+
<a name='L186'></a><a href='#L186'>186</a>
|
|
252
|
+
<a name='L187'></a><a href='#L187'>187</a>
|
|
253
|
+
<a name='L188'></a><a href='#L188'>188</a>
|
|
254
|
+
<a name='L189'></a><a href='#L189'>189</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
255
|
+
<span class="cline-any cline-neutral"> </span>
|
|
256
|
+
<span class="cline-any cline-neutral"> </span>
|
|
257
|
+
<span class="cline-any cline-neutral"> </span>
|
|
258
|
+
<span class="cline-any cline-neutral"> </span>
|
|
259
|
+
<span class="cline-any cline-neutral"> </span>
|
|
235
260
|
<span class="cline-any cline-neutral"> </span>
|
|
236
261
|
<span class="cline-any cline-neutral"> </span>
|
|
237
262
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -252,39 +277,69 @@
|
|
|
252
277
|
<span class="cline-any cline-neutral"> </span>
|
|
253
278
|
<span class="cline-any cline-neutral"> </span>
|
|
254
279
|
<span class="cline-any cline-yes">67x</span>
|
|
280
|
+
<span class="cline-any cline-neutral"> </span>
|
|
281
|
+
<span class="cline-any cline-neutral"> </span>
|
|
255
282
|
<span class="cline-any cline-yes">67x</span>
|
|
256
|
-
<span class="cline-any cline-yes">20178x</span>
|
|
257
|
-
<span class="cline-any cline-yes">3x</span>
|
|
258
283
|
<span class="cline-any cline-neutral"> </span>
|
|
259
284
|
<span class="cline-any cline-neutral"> </span>
|
|
260
285
|
<span class="cline-any cline-neutral"> </span>
|
|
286
|
+
<span class="cline-any cline-yes">67x</span>
|
|
287
|
+
<span class="cline-any cline-yes">9x</span>
|
|
261
288
|
<span class="cline-any cline-neutral"> </span>
|
|
262
289
|
<span class="cline-any cline-neutral"> </span>
|
|
263
|
-
<span class="cline-any cline-yes">
|
|
290
|
+
<span class="cline-any cline-yes">67x</span>
|
|
291
|
+
<span class="cline-any cline-yes">61x</span>
|
|
292
|
+
<span class="cline-any cline-neutral"> </span>
|
|
293
|
+
<span class="cline-any cline-neutral"> </span>
|
|
294
|
+
<span class="cline-any cline-yes">67x</span>
|
|
295
|
+
<span class="cline-any cline-neutral"> </span>
|
|
296
|
+
<span class="cline-any cline-neutral"> </span>
|
|
297
|
+
<span class="cline-any cline-neutral"> </span>
|
|
298
|
+
<span class="cline-any cline-neutral"> </span>
|
|
299
|
+
<span class="cline-any cline-neutral"> </span>
|
|
300
|
+
<span class="cline-any cline-neutral"> </span>
|
|
301
|
+
<span class="cline-any cline-neutral"> </span>
|
|
302
|
+
<span class="cline-any cline-neutral"> </span>
|
|
303
|
+
<span class="cline-any cline-neutral"> </span>
|
|
304
|
+
<span class="cline-any cline-neutral"> </span>
|
|
305
|
+
<span class="cline-any cline-neutral"> </span>
|
|
306
|
+
<span class="cline-any cline-yes">11x</span>
|
|
307
|
+
<span class="cline-any cline-yes">10x</span>
|
|
308
|
+
<span class="cline-any cline-neutral"> </span>
|
|
264
309
|
<span class="cline-any cline-neutral"> </span>
|
|
265
310
|
<span class="cline-any cline-neutral"> </span>
|
|
266
311
|
<span class="cline-any cline-neutral"> </span>
|
|
267
312
|
<span class="cline-any cline-neutral"> </span>
|
|
313
|
+
<span class="cline-any cline-neutral"> </span>
|
|
314
|
+
<span class="cline-any cline-yes">67x</span>
|
|
268
315
|
<span class="cline-any cline-yes">67x</span>
|
|
269
316
|
<span class="cline-any cline-yes">20178x</span>
|
|
270
|
-
<span class="cline-any cline-yes">
|
|
271
|
-
<span class="cline-any cline-
|
|
317
|
+
<span class="cline-any cline-yes">3x</span>
|
|
318
|
+
<span class="cline-any cline-neutral"> </span>
|
|
319
|
+
<span class="cline-any cline-neutral"> </span>
|
|
272
320
|
<span class="cline-any cline-neutral"> </span>
|
|
273
321
|
<span class="cline-any cline-neutral"> </span>
|
|
274
322
|
<span class="cline-any cline-neutral"> </span>
|
|
323
|
+
<span class="cline-any cline-yes">20175x</span>
|
|
275
324
|
<span class="cline-any cline-neutral"> </span>
|
|
276
325
|
<span class="cline-any cline-neutral"> </span>
|
|
326
|
+
<span class="cline-any cline-yes">67x</span>
|
|
277
327
|
<span class="cline-any cline-neutral"> </span>
|
|
278
328
|
<span class="cline-any cline-neutral"> </span>
|
|
279
329
|
<span class="cline-any cline-neutral"> </span>
|
|
280
330
|
<span class="cline-any cline-neutral"> </span>
|
|
281
331
|
<span class="cline-any cline-neutral"> </span>
|
|
282
|
-
<span class="cline-any cline-yes">67x</span>
|
|
283
|
-
<span class="cline-any cline-yes">9x</span>
|
|
284
332
|
<span class="cline-any cline-neutral"> </span>
|
|
285
333
|
<span class="cline-any cline-neutral"> </span>
|
|
286
334
|
<span class="cline-any cline-yes">67x</span>
|
|
287
|
-
<span class="cline-any cline-yes">
|
|
335
|
+
<span class="cline-any cline-yes">20178x</span>
|
|
336
|
+
<span class="cline-any cline-yes">20172x</span>
|
|
337
|
+
<span class="cline-any cline-yes">7x</span>
|
|
338
|
+
<span class="cline-any cline-neutral"> </span>
|
|
339
|
+
<span class="cline-any cline-neutral"> </span>
|
|
340
|
+
<span class="cline-any cline-neutral"> </span>
|
|
341
|
+
<span class="cline-any cline-neutral"> </span>
|
|
342
|
+
<span class="cline-any cline-neutral"> </span>
|
|
288
343
|
<span class="cline-any cline-neutral"> </span>
|
|
289
344
|
<span class="cline-any cline-neutral"> </span>
|
|
290
345
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -324,21 +379,6 @@
|
|
|
324
379
|
<span class="cline-any cline-neutral"> </span>
|
|
325
380
|
<span class="cline-any cline-neutral"> </span>
|
|
326
381
|
<span class="cline-any cline-neutral"> </span>
|
|
327
|
-
<span class="cline-any cline-yes">61x</span>
|
|
328
|
-
<span class="cline-any cline-neutral"> </span>
|
|
329
|
-
<span class="cline-any cline-neutral"> </span>
|
|
330
|
-
<span class="cline-any cline-neutral"> </span>
|
|
331
|
-
<span class="cline-any cline-neutral"> </span>
|
|
332
|
-
<span class="cline-any cline-neutral"> </span>
|
|
333
|
-
<span class="cline-any cline-neutral"> </span>
|
|
334
|
-
<span class="cline-any cline-neutral"> </span>
|
|
335
|
-
<span class="cline-any cline-neutral"> </span>
|
|
336
|
-
<span class="cline-any cline-neutral"> </span>
|
|
337
|
-
<span class="cline-any cline-neutral"> </span>
|
|
338
|
-
<span class="cline-any cline-neutral"> </span>
|
|
339
|
-
<span class="cline-any cline-yes">9x</span>
|
|
340
|
-
<span class="cline-any cline-yes">9x</span>
|
|
341
|
-
<span class="cline-any cline-neutral"> </span>
|
|
342
382
|
<span class="cline-any cline-neutral"> </span>
|
|
343
383
|
<span class="cline-any cline-neutral"> </span>
|
|
344
384
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -403,6 +443,11 @@
|
|
|
403
443
|
import { ValidationResult } from "./contracts/ValidationResult.js";
|
|
404
444
|
import { ValidationError } from "./contracts/ValidationError.js";
|
|
405
445
|
import { TaskGraph } from "./TaskGraph.js";
|
|
446
|
+
import {
|
|
447
|
+
ERROR_CYCLE,
|
|
448
|
+
ERROR_DUPLICATE_TASK,
|
|
449
|
+
ERROR_MISSING_DEPENDENCY,
|
|
450
|
+
} from "./contracts/ErrorTypes.js";
|
|
406
451
|
|
|
407
452
|
export class TaskGraphValidator implements ITaskGraphValidator {
|
|
408
453
|
/**
|
|
@@ -419,11 +464,46 @@ export class TaskGraphValidator implements ITaskGraphValidator {
|
|
|
419
464
|
const errors: ValidationError[] = [];
|
|
420
465
|
|
|
421
466
|
// 1. Check for duplicate tasks
|
|
467
|
+
const taskIds = this.checkDuplicateTasks(taskGraph, errors);
|
|
468
|
+
|
|
469
|
+
// 2. Check for missing dependencies
|
|
470
|
+
this.checkMissingDependencies(taskGraph, taskIds, errors);
|
|
471
|
+
|
|
472
|
+
// 3. Check for cycles
|
|
473
|
+
// Only run cycle detection if there are no missing dependencies, otherwise we might chase non-existent nodes.
|
|
474
|
+
const hasMissingDependencies = errors.some(
|
|
475
|
+
(e) => e.type === ERROR_MISSING_DEPENDENCY
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
if (!hasMissingDependencies) {
|
|
479
|
+
this.checkCycles(taskGraph, errors);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return {
|
|
483
|
+
isValid: errors.length === 0,
|
|
484
|
+
errors,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Creates a human-readable error message from a validation result.
|
|
490
|
+
* @param result The validation result containing errors.
|
|
491
|
+
* @returns A formatted error string.
|
|
492
|
+
*/
|
|
493
|
+
createErrorMessage(result: ValidationResult): string {
|
|
494
|
+
const errorDetails = result.errors.map((e) => e.message);
|
|
495
|
+
return `Task graph validation failed: ${errorDetails.join("; ")}`;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
private checkDuplicateTasks(
|
|
499
|
+
taskGraph: TaskGraph,
|
|
500
|
+
errors: ValidationError[]
|
|
501
|
+
): Set<string> {
|
|
422
502
|
const taskIds = new Set<string>();
|
|
423
503
|
for (const task of taskGraph.tasks) {
|
|
424
504
|
if (taskIds.has(task.id)) {
|
|
425
505
|
errors.push({
|
|
426
|
-
type:
|
|
506
|
+
type: ERROR_DUPLICATE_TASK,
|
|
427
507
|
message: `Duplicate task detected with ID: ${task.id}`,
|
|
428
508
|
details: { taskId: task.id },
|
|
429
509
|
});
|
|
@@ -431,33 +511,28 @@ export class TaskGraphValidator implements ITaskGraphValidator {
|
|
|
431
511
|
taskIds.add(task.id);
|
|
432
512
|
}
|
|
433
513
|
}
|
|
514
|
+
return taskIds;
|
|
515
|
+
}
|
|
434
516
|
|
|
435
|
-
|
|
517
|
+
private checkMissingDependencies(
|
|
518
|
+
taskGraph: TaskGraph,
|
|
519
|
+
taskIds: Set<string>,
|
|
520
|
+
errors: ValidationError[]
|
|
521
|
+
): void {
|
|
436
522
|
for (const task of taskGraph.tasks) {
|
|
437
523
|
for (const dependenceId of task.dependencies) {
|
|
438
524
|
if (!taskIds.has(dependenceId)) {
|
|
439
525
|
errors.push({
|
|
440
|
-
type:
|
|
526
|
+
type: ERROR_MISSING_DEPENDENCY,
|
|
441
527
|
message: `Task '${task.id}' depends on missing task '${dependenceId}'`,
|
|
442
528
|
details: { taskId: task.id, missingDependencyId: dependenceId },
|
|
443
529
|
});
|
|
444
530
|
}
|
|
445
531
|
}
|
|
446
532
|
}
|
|
533
|
+
}
|
|
447
534
|
|
|
448
|
-
|
|
449
|
-
// Only run cycle detection if there are no missing dependencies, otherwise we might chase non-existent nodes.
|
|
450
|
-
const hasMissingDependencies = errors.some(
|
|
451
|
-
(e) => e.type === "missing_dependency"
|
|
452
|
-
);
|
|
453
|
-
|
|
454
|
-
if (hasMissingDependencies) {
|
|
455
|
-
return {
|
|
456
|
-
isValid: errors.length === 0,
|
|
457
|
-
errors,
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
|
|
535
|
+
private checkCycles(taskGraph: TaskGraph, errors: ValidationError[]): void {
|
|
461
536
|
// Build adjacency list
|
|
462
537
|
const adjacencyList = new Map<string, string[]>();
|
|
463
538
|
for (const task of taskGraph.tasks) {
|
|
@@ -483,7 +558,7 @@ export class TaskGraphValidator implements ITaskGraphValidator {
|
|
|
483
558
|
const cyclePath = path.slice(cycleStartIndex);
|
|
484
559
|
|
|
485
560
|
errors.push({
|
|
486
|
-
type:
|
|
561
|
+
type: ERROR_CYCLE,
|
|
487
562
|
message: `Cycle detected: ${cyclePath.join(" -> ")}`,
|
|
488
563
|
details: { cyclePath },
|
|
489
564
|
});
|
|
@@ -491,21 +566,6 @@ export class TaskGraphValidator implements ITaskGraphValidator {
|
|
|
491
566
|
break;
|
|
492
567
|
}
|
|
493
568
|
}
|
|
494
|
-
|
|
495
|
-
return {
|
|
496
|
-
isValid: errors.length === 0,
|
|
497
|
-
errors,
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Creates a human-readable error message from a validation result.
|
|
503
|
-
* @param result The validation result containing errors.
|
|
504
|
-
* @returns A formatted error string.
|
|
505
|
-
*/
|
|
506
|
-
createErrorMessage(result: ValidationResult): string {
|
|
507
|
-
const errorDetails = result.errors.map((e) => e.message);
|
|
508
|
-
return `Task graph validation failed: ${errorDetails.join("; ")}`;
|
|
509
569
|
}
|
|
510
570
|
|
|
511
571
|
private detectCycle(
|
|
@@ -574,7 +634,7 @@ export class TaskGraphValidator implements ITaskGraphValidator {
|
|
|
574
634
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
575
635
|
Code coverage generated by
|
|
576
636
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
577
|
-
at 2026-01-
|
|
637
|
+
at 2026-01-21T01:05:21.402Z
|
|
578
638
|
</div>
|
|
579
639
|
<script src="../prettify.js"></script>
|
|
580
640
|
<script>
|
|
@@ -25,7 +25,7 @@
|
|
|
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'>48/48</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
@@ -265,7 +265,12 @@
|
|
|
265
265
|
<a name='L200'></a><a href='#L200'>200</a>
|
|
266
266
|
<a name='L201'></a><a href='#L201'>201</a>
|
|
267
267
|
<a name='L202'></a><a href='#L202'>202</a>
|
|
268
|
-
<a name='L203'></a><a href='#L203'>203</a
|
|
268
|
+
<a name='L203'></a><a href='#L203'>203</a>
|
|
269
|
+
<a name='L204'></a><a href='#L204'>204</a>
|
|
270
|
+
<a name='L205'></a><a href='#L205'>205</a>
|
|
271
|
+
<a name='L206'></a><a href='#L206'>206</a>
|
|
272
|
+
<a name='L207'></a><a href='#L207'>207</a>
|
|
273
|
+
<a name='L208'></a><a href='#L208'>208</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
269
274
|
<span class="cline-any cline-neutral"> </span>
|
|
270
275
|
<span class="cline-any cline-neutral"> </span>
|
|
271
276
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -346,23 +351,14 @@
|
|
|
346
351
|
<span class="cline-any cline-neutral"> </span>
|
|
347
352
|
<span class="cline-any cline-yes">5x</span>
|
|
348
353
|
<span class="cline-any cline-neutral"> </span>
|
|
349
|
-
<span class="cline-any cline-neutral"> </span>
|
|
350
|
-
<span class="cline-any cline-neutral"> </span>
|
|
351
|
-
<span class="cline-any cline-neutral"> </span>
|
|
352
|
-
<span class="cline-any cline-neutral"> </span>
|
|
353
|
-
<span class="cline-any cline-neutral"> </span>
|
|
354
|
-
<span class="cline-any cline-yes">15x</span>
|
|
355
354
|
<span class="cline-any cline-yes">27x</span>
|
|
356
355
|
<span class="cline-any cline-neutral"> </span>
|
|
357
|
-
<span class="cline-any cline-neutral"> </span>
|
|
358
356
|
<span class="cline-any cline-yes">5x</span>
|
|
359
|
-
<span class="cline-any cline-neutral"> </span>
|
|
360
|
-
<span class="cline-any cline-neutral"> </span>
|
|
361
|
-
<span class="cline-any cline-neutral"> </span>
|
|
362
357
|
<span class="cline-any cline-yes">15x</span>
|
|
363
358
|
<span class="cline-any cline-neutral"> </span>
|
|
364
359
|
<span class="cline-any cline-neutral"> </span>
|
|
365
360
|
<span class="cline-any cline-neutral"> </span>
|
|
361
|
+
<span class="cline-any cline-neutral"> </span>
|
|
366
362
|
<span class="cline-any cline-yes">5x</span>
|
|
367
363
|
<span class="cline-any cline-yes">15x</span>
|
|
368
364
|
<span class="cline-any cline-yes">5x</span>
|
|
@@ -426,15 +422,32 @@
|
|
|
426
422
|
<span class="cline-any cline-neutral"> </span>
|
|
427
423
|
<span class="cline-any cline-neutral"> </span>
|
|
428
424
|
<span class="cline-any cline-neutral"> </span>
|
|
429
|
-
<span class="cline-any cline-neutral"> </span>
|
|
430
425
|
<span class="cline-any cline-yes">58x</span>
|
|
431
426
|
<span class="cline-any cline-yes">5x</span>
|
|
432
|
-
<span class="cline-any cline-yes">5x</span>
|
|
433
|
-
<span class="cline-any cline-yes">3x</span>
|
|
434
427
|
<span class="cline-any cline-neutral"> </span>
|
|
435
428
|
<span class="cline-any cline-neutral"> </span>
|
|
436
429
|
<span class="cline-any cline-neutral"> </span>
|
|
437
430
|
<span class="cline-any cline-neutral"> </span>
|
|
431
|
+
<span class="cline-any cline-neutral"> </span>
|
|
432
|
+
<span class="cline-any cline-neutral"> </span>
|
|
433
|
+
<span class="cline-any cline-yes">44x</span>
|
|
434
|
+
<span class="cline-any cline-neutral"> </span>
|
|
435
|
+
<span class="cline-any cline-neutral"> </span>
|
|
436
|
+
<span class="cline-any cline-neutral"> </span>
|
|
437
|
+
<span class="cline-any cline-neutral"> </span>
|
|
438
|
+
<span class="cline-any cline-neutral"> </span>
|
|
439
|
+
<span class="cline-any cline-neutral"> </span>
|
|
440
|
+
<span class="cline-any cline-neutral"> </span>
|
|
441
|
+
<span class="cline-any cline-neutral"> </span>
|
|
442
|
+
<span class="cline-any cline-neutral"> </span>
|
|
443
|
+
<span class="cline-any cline-neutral"> </span>
|
|
444
|
+
<span class="cline-any cline-neutral"> </span>
|
|
445
|
+
<span class="cline-any cline-neutral"> </span>
|
|
446
|
+
<span class="cline-any cline-yes">5x</span>
|
|
447
|
+
<span class="cline-any cline-yes">5x</span>
|
|
448
|
+
<span class="cline-any cline-yes">3x</span>
|
|
449
|
+
<span class="cline-any cline-neutral"> </span>
|
|
450
|
+
<span class="cline-any cline-neutral"> </span>
|
|
438
451
|
<span class="cline-any cline-yes">5x</span>
|
|
439
452
|
<span class="cline-any cline-neutral"> </span>
|
|
440
453
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -463,9 +476,6 @@
|
|
|
463
476
|
<span class="cline-any cline-neutral"> </span>
|
|
464
477
|
<span class="cline-any cline-neutral"> </span>
|
|
465
478
|
<span class="cline-any cline-neutral"> </span>
|
|
466
|
-
<span class="cline-any cline-yes">44x</span>
|
|
467
|
-
<span class="cline-any cline-neutral"> </span>
|
|
468
|
-
<span class="cline-any cline-neutral"> </span>
|
|
469
479
|
<span class="cline-any cline-neutral"> </span>
|
|
470
480
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { TaskStep } from "./TaskStep.js";
|
|
471
481
|
import { TaskResult } from "./TaskResult.js";
|
|
@@ -548,23 +558,14 @@ export class TaskRunner<TContext> {
|
|
|
548
558
|
public static getMermaidGraph<T>(steps: TaskStep<T>[]): string {
|
|
549
559
|
const graphLines = ["graph TD"];
|
|
550
560
|
|
|
551
|
-
// Helper to sanitize node names or wrap them if needed
|
|
552
|
-
// For simplicity, we just wrap in quotes and use the name as ID if it's simple
|
|
553
|
-
// or generate an ID if strictly needed. Here we assume names are unique IDs.
|
|
554
|
-
// We will wrap names in quotes for the label, but use the name as the ID.
|
|
555
|
-
// Actually, Mermaid ID cannot have spaces without quotes.
|
|
556
|
-
const safeId = (name: string) => JSON.stringify(name);
|
|
557
561
|
const sanitize = (name: string) => this.sanitizeMermaidId(name);
|
|
558
562
|
|
|
559
|
-
// Add all nodes first to ensure they exist
|
|
560
563
|
for (const step of steps) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
graphLines.push(` ${sanitize(step.name)}[${safeId(step.name)}]`);
|
|
564
|
+
graphLines.push(
|
|
565
|
+
` ${sanitize(step.name)}[${JSON.stringify(step.name)}]`
|
|
566
|
+
);
|
|
565
567
|
}
|
|
566
568
|
|
|
567
|
-
// Add edges
|
|
568
569
|
for (const step of steps) {
|
|
569
570
|
if (step.dependencies) {
|
|
570
571
|
for (const dep of step.dependencies) {
|
|
@@ -628,44 +629,58 @@ export class TaskRunner<TContext> {
|
|
|
628
629
|
config?.concurrency
|
|
629
630
|
);
|
|
630
631
|
|
|
631
|
-
// We need to handle the timeout cleanup properly.
|
|
632
632
|
if (config?.timeout !== undefined) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
633
|
+
return this.executeWithTimeout(
|
|
634
|
+
executor,
|
|
635
|
+
steps,
|
|
636
|
+
config.timeout,
|
|
637
|
+
config.signal
|
|
638
|
+
);
|
|
639
|
+
} else {
|
|
640
|
+
return executor.execute(steps, config?.signal);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
639
643
|
|
|
640
|
-
|
|
641
|
-
|
|
644
|
+
/**
|
|
645
|
+
* Executes tasks with a timeout, ensuring resources are cleaned up.
|
|
646
|
+
*/
|
|
647
|
+
private async executeWithTimeout(
|
|
648
|
+
executor: WorkflowExecutor<TContext>,
|
|
649
|
+
steps: TaskStep<TContext>[],
|
|
650
|
+
timeout: number,
|
|
651
|
+
signal?: AbortSignal
|
|
652
|
+
): Promise<Map<string, TaskResult>> {
|
|
653
|
+
const controller = new AbortController();
|
|
654
|
+
const timeoutId = setTimeout(() => {
|
|
655
|
+
controller.abort(new Error(`Workflow timed out after ${timeout}ms`));
|
|
656
|
+
}, timeout);
|
|
642
657
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
if (config.signal.aborted) {
|
|
646
|
-
// If already aborted, use it directly (WorkflowExecutor handles early abort)
|
|
647
|
-
// We can cancel timeout immediately
|
|
648
|
-
clearTimeout(timeoutId);
|
|
649
|
-
effectiveSignal = config.signal;
|
|
650
|
-
} else {
|
|
651
|
-
// Listen to user signal to abort our controller
|
|
652
|
-
onAbort = () => {
|
|
653
|
-
controller.abort(config.signal?.reason);
|
|
654
|
-
};
|
|
655
|
-
config.signal.addEventListener("abort", onAbort);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
+
let effectiveSignal = controller.signal;
|
|
659
|
+
let onAbort: (() => void) | undefined;
|
|
658
660
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
661
|
+
// Handle combination of signals if user provided one
|
|
662
|
+
if (signal) {
|
|
663
|
+
if (signal.aborted) {
|
|
664
|
+
// If already aborted, use it directly (WorkflowExecutor handles early abort)
|
|
665
|
+
// We can cancel timeout immediately
|
|
662
666
|
clearTimeout(timeoutId);
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
667
|
+
effectiveSignal = signal;
|
|
668
|
+
} else {
|
|
669
|
+
// Listen to user signal to abort our controller
|
|
670
|
+
onAbort = () => {
|
|
671
|
+
controller.abort(signal.reason);
|
|
672
|
+
};
|
|
673
|
+
signal.addEventListener("abort", onAbort);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
try {
|
|
678
|
+
return await executor.execute(steps, effectiveSignal);
|
|
679
|
+
} finally {
|
|
680
|
+
clearTimeout(timeoutId);
|
|
681
|
+
if (signal && onAbort) {
|
|
682
|
+
signal.removeEventListener("abort", onAbort);
|
|
666
683
|
}
|
|
667
|
-
} else {
|
|
668
|
-
return executor.execute(steps, config?.signal);
|
|
669
684
|
}
|
|
670
685
|
}
|
|
671
686
|
}
|
|
@@ -676,7 +691,7 @@ export class TaskRunner<TContext> {
|
|
|
676
691
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
677
692
|
Code coverage generated by
|
|
678
693
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
679
|
-
at 2026-01-
|
|
694
|
+
at 2026-01-21T01:05:21.402Z
|
|
680
695
|
</div>
|
|
681
696
|
<script src="../prettify.js"></script>
|
|
682
697
|
<script>
|
|
@@ -322,7 +322,7 @@ export class TaskRunnerBuilder<TContext> {
|
|
|
322
322
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
323
323
|
Code coverage generated by
|
|
324
324
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
325
|
-
at 2026-01-
|
|
325
|
+
at 2026-01-21T01:05:21.402Z
|
|
326
326
|
</div>
|
|
327
327
|
<script src="../prettify.js"></script>
|
|
328
328
|
<script>
|
|
@@ -139,7 +139,7 @@ export interface TaskRunnerExecutionConfig {
|
|
|
139
139
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
140
140
|
Code coverage generated by
|
|
141
141
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
142
|
-
at 2026-01-
|
|
142
|
+
at 2026-01-21T01:05:21.402Z
|
|
143
143
|
</div>
|
|
144
144
|
<script src="../prettify.js"></script>
|
|
145
145
|
<script>
|