@decaf-ts/core 0.28.1 → 0.29.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.
Files changed (40) hide show
  1. package/README.md +1 -1
  2. package/dist/core.cjs +1 -1
  3. package/dist/core.cjs.map +1 -1
  4. package/dist/core.js +1 -1
  5. package/dist/core.js.map +1 -1
  6. package/lib/cjs/index.cjs +3 -3
  7. package/lib/cjs/tasks/TaskContext.cjs +3 -0
  8. package/lib/cjs/tasks/TaskContext.cjs.map +1 -1
  9. package/lib/cjs/tasks/TaskEngine.cjs +148 -69
  10. package/lib/cjs/tasks/TaskEngine.cjs.map +1 -1
  11. package/lib/cjs/tasks/builder.cjs +4 -0
  12. package/lib/cjs/tasks/builder.cjs.map +1 -1
  13. package/lib/cjs/tasks/constants.cjs +1 -0
  14. package/lib/cjs/tasks/constants.cjs.map +1 -1
  15. package/lib/cjs/tasks/models/TaskStepSpecModel.cjs +6 -0
  16. package/lib/cjs/tasks/models/TaskStepSpecModel.cjs.map +1 -1
  17. package/lib/esm/index.js +3 -3
  18. package/lib/esm/tasks/TaskContext.js +3 -0
  19. package/lib/esm/tasks/TaskContext.js.map +1 -1
  20. package/lib/esm/tasks/TaskEngine.js +148 -69
  21. package/lib/esm/tasks/TaskEngine.js.map +1 -1
  22. package/lib/esm/tasks/builder.js +4 -0
  23. package/lib/esm/tasks/builder.js.map +1 -1
  24. package/lib/esm/tasks/constants.js +1 -0
  25. package/lib/esm/tasks/constants.js.map +1 -1
  26. package/lib/esm/tasks/models/TaskStepSpecModel.js +6 -0
  27. package/lib/esm/tasks/models/TaskStepSpecModel.js.map +1 -1
  28. package/lib/types/index.d.cts +3 -3
  29. package/lib/types/index.d.mts +3 -3
  30. package/lib/types/tasks/TaskContext.d.cts +2 -0
  31. package/lib/types/tasks/TaskContext.d.mts +2 -0
  32. package/lib/types/tasks/TaskEngine.d.cts +5 -0
  33. package/lib/types/tasks/TaskEngine.d.mts +5 -0
  34. package/lib/types/tasks/builder.d.cts +1 -0
  35. package/lib/types/tasks/builder.d.mts +1 -0
  36. package/lib/types/tasks/models/TaskStepSpecModel.d.cts +1 -0
  37. package/lib/types/tasks/models/TaskStepSpecModel.d.mts +1 -0
  38. package/lib/types/tasks/types.d.cts +4 -0
  39. package/lib/types/tasks/types.d.mts +4 -0
  40. package/package.json +1 -1
@@ -33,6 +33,7 @@ exports.TasksKey = "tasks";
33
33
  exports.DefaultTaskEngineConfig = {
34
34
  workerId: "default-worker",
35
35
  concurrency: 10,
36
+ maxConcurrentCompositeSteps: -1,
36
37
  leaseMs: 60000,
37
38
  pollMsIdle: 1000,
38
39
  pollMsBusy: 500,
@@ -1 +1 @@
1
- {"version":3,"file":"tasks/constants.cjs","sourceRoot":"","sources":["tasks/constants.js"],"names":[],"mappings":";;;AACA,CAAC,UAAU,UAAU;IACjB,UAAU,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAChC,UAAU,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IACpC,UAAU,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC;AAClD,CAAC,CAAC,CAAC,kBAAU,IAAI,CAAC,kBAAU,GAAG,EAAE,CAAC,CAAC,CAAC;AAEpC,CAAC,UAAU,eAAe;IACtB,eAAe,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;IAC/C,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AACvC,CAAC,CAAC,CAAC,uBAAe,IAAI,CAAC,uBAAe,GAAG,EAAE,CAAC,CAAC,CAAC;AAE9C,CAAC,UAAU,cAAc;IACrB,cAAc,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAChC,cAAc,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AACpC,CAAC,CAAC,CAAC,sBAAc,IAAI,CAAC,sBAAc,GAAG,EAAE,CAAC,CAAC,CAAC;AAE5C,CAAC,UAAU,aAAa;IACpB,aAAa,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IACnC,aAAa,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IACnC,aAAa,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IAC7B,aAAa,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IACvC,aAAa,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AACjC,CAAC,CAAC,CAAC,qBAAa,IAAI,CAAC,qBAAa,GAAG,EAAE,CAAC,CAAC,CAAC;AAE1C,CAAC,UAAU,QAAQ;IACf,QAAQ,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;AACxC,CAAC,CAAC,CAAC,gBAAQ,IAAI,CAAC,gBAAQ,GAAG,EAAE,CAAC,CAAC,CAAC;AACnB,QAAA,QAAQ,GAAG,OAAO,CAAC;AACnB,QAAA,uBAAuB,GAAG;IACnC,QAAQ,EAAE,gBAAgB;IAC1B,WAAW,EAAE,EAAE;IACf,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,GAAG;IACf,UAAU,EAAE,GAAG;IACf,gBAAgB,EAAE,CAAC;IACnB,gBAAgB,EAAE,GAAG;IACrB,uBAAuB,EAAE,EAAE;IAC3B,yBAAyB,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI;IACxC,YAAY,EAAE;QACV,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,IAAI;QACnB,cAAc,EAAE,EAAE,GAAG,IAAI;KAC5B;CACJ,CAAC;AACF,qCAAqC"}
1
+ {"version":3,"file":"tasks/constants.cjs","sourceRoot":"","sources":["tasks/constants.js"],"names":[],"mappings":";;;AACA,CAAC,UAAU,UAAU;IACjB,UAAU,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAChC,UAAU,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IACpC,UAAU,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC;AAClD,CAAC,CAAC,CAAC,kBAAU,IAAI,CAAC,kBAAU,GAAG,EAAE,CAAC,CAAC,CAAC;AAEpC,CAAC,UAAU,eAAe;IACtB,eAAe,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;IAC/C,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AACvC,CAAC,CAAC,CAAC,uBAAe,IAAI,CAAC,uBAAe,GAAG,EAAE,CAAC,CAAC,CAAC;AAE9C,CAAC,UAAU,cAAc;IACrB,cAAc,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAChC,cAAc,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AACpC,CAAC,CAAC,CAAC,sBAAc,IAAI,CAAC,sBAAc,GAAG,EAAE,CAAC,CAAC,CAAC;AAE5C,CAAC,UAAU,aAAa;IACpB,aAAa,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IACnC,aAAa,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IACnC,aAAa,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IAC7B,aAAa,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IACvC,aAAa,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AACjC,CAAC,CAAC,CAAC,qBAAa,IAAI,CAAC,qBAAa,GAAG,EAAE,CAAC,CAAC,CAAC;AAE1C,CAAC,UAAU,QAAQ;IACf,QAAQ,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;AACxC,CAAC,CAAC,CAAC,gBAAQ,IAAI,CAAC,gBAAQ,GAAG,EAAE,CAAC,CAAC,CAAC;AACnB,QAAA,QAAQ,GAAG,OAAO,CAAC;AACnB,QAAA,uBAAuB,GAAG;IACnC,QAAQ,EAAE,gBAAgB;IAC1B,WAAW,EAAE,EAAE;IACf,2BAA2B,EAAE,CAAC,CAAC;IAC/B,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,GAAG;IACf,UAAU,EAAE,GAAG;IACf,gBAAgB,EAAE,CAAC;IACnB,gBAAgB,EAAE,GAAG;IACrB,uBAAuB,EAAE,EAAE;IAC3B,yBAAyB,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI;IACxC,YAAY,EAAE;QACV,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,IAAI;QACnB,cAAc,EAAE,EAAE,GAAG,IAAI;KAC5B;CACJ,CAAC;AACF,qCAAqC"}
@@ -23,6 +23,7 @@ const TaskBackoffModel_js_1 = require("./TaskBackoffModel.cjs");
23
23
  let TaskStepSpecModel = class TaskStepSpecModel extends decorator_validation_1.Model {
24
24
  constructor(arg) {
25
25
  super(arg);
26
+ this.allowConcurrent = false;
26
27
  this.canFail = false;
27
28
  }
28
29
  };
@@ -47,6 +48,11 @@ __decorate([
47
48
  (0, decoration_1.prop)(),
48
49
  __metadata("design:type", String)
49
50
  ], TaskStepSpecModel.prototype, "lock", void 0);
51
+ __decorate([
52
+ (0, decoration_1.prop)(),
53
+ (0, decoration_1.description)("When true, compatible steps that share the same lock may run concurrently"),
54
+ __metadata("design:type", Boolean)
55
+ ], TaskStepSpecModel.prototype, "allowConcurrent", void 0);
50
56
  __decorate([
51
57
  (0, decoration_1.description)("Task-step dependencies. Supports '<taskId>' or '<taskId>:<step index|step reference>'"),
52
58
  (0, decoration_1.prop)(),
@@ -1 +1 @@
1
- {"version":3,"file":"tasks/models/TaskStepSpecModel.cjs","sourceRoot":"","sources":["tasks/models/TaskStepSpecModel.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tasks/models/TaskStepSpecModel.cjs","sourceRoot":"","sources":["tasks/models/TaskStepSpecModel.js"],"names":[],"mappings":"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"}
package/lib/esm/index.js CHANGED
@@ -33,21 +33,21 @@ export * from "./persistence/index.js";
33
33
  * @const VERSION
34
34
  * @memberOf module:core
35
35
  */
36
- export const VERSION = "0.28.0";
36
+ export const VERSION = "0.28.1";
37
37
  /**
38
38
  * @description Represents the current commit hash of the module build.
39
39
  * @summary Stores the current git commit hash for the package. The build replaces
40
40
  * the placeholder with the actual commit hash at publish time.
41
41
  * @const COMMIT
42
42
  */
43
- export const COMMIT = "19de947";
43
+ export const COMMIT = "49b1386";
44
44
  /**
45
45
  * @description Represents the full version string of the module.
46
46
  * @summary Stores the semver version and commit hash for the package.
47
47
  * The build replaces the placeholder with the actual `<version>-<commit>` value at publish time.
48
48
  * @const FULL_VERSION
49
49
  */
50
- export const FULL_VERSION = "0.28.0-19de947";
50
+ export const FULL_VERSION = "0.28.1-49b1386";
51
51
  /**
52
52
  * @description Stores the current package version
53
53
  * @summary A constant representing the version of the core package
@@ -34,6 +34,9 @@ export class TaskContext extends Context {
34
34
  get heartbeat() {
35
35
  return this.get("heartbeat");
36
36
  }
37
+ get stepWriteLock() {
38
+ return this.get("stepWriteLock");
39
+ }
37
40
  cacheResult(taskId, payload) {
38
41
  const cache = (this.cache.has("resultCache") && this.cache.get("resultCache")) ||
39
42
  {};
@@ -1 +1 @@
1
- {"version":3,"file":"TaskContext.js","sourceRoot":"","sources":["../../../src/tasks/TaskContext.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskContext.js","sourceRoot":"","sources":["../../../src/tasks/TaskContext.ts"],"names":[],"mappings":"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"}
@@ -437,6 +437,42 @@ export class TaskEngine extends AbsContextual {
437
437
  : undefined;
438
438
  return !(await this.hasLockConflict(task, stepIndex, ctx));
439
439
  }
440
+ getCompositeStepConcurrencyLimit() {
441
+ const limit = this.config.maxConcurrentCompositeSteps ?? -1;
442
+ if (limit === 0)
443
+ return 1;
444
+ if (limit < 0)
445
+ return Number.POSITIVE_INFINITY;
446
+ return Math.max(1, limit);
447
+ }
448
+ isConcurrentCompositeStep(step) {
449
+ return Boolean(step.allowConcurrent && step.lock);
450
+ }
451
+ createCompositeStepContext(context, stepIndex) {
452
+ return TaskEngine.createTaskContext(context, { step: stepIndex });
453
+ }
454
+ async withStepWriteLock(ctx, fn) {
455
+ const lock = ctx.stepWriteLock;
456
+ await lock.acquire();
457
+ try {
458
+ return await fn();
459
+ }
460
+ finally {
461
+ lock.release();
462
+ }
463
+ }
464
+ recalculateCompositeCurrentStep(steps, results) {
465
+ let next = 0;
466
+ while (next < steps.length) {
467
+ const result = results[next];
468
+ if (!result)
469
+ break;
470
+ if (result.status === TaskStatus.FAILED && !steps[next]?.canFail)
471
+ break;
472
+ next += 1;
473
+ }
474
+ return next;
475
+ }
440
476
  // -------------------------
441
477
  // Execution
442
478
  // -------------------------
@@ -447,6 +483,7 @@ export class TaskEngine extends AbsContextual {
447
483
  let logPipeQueue = Promise.resolve();
448
484
  const taskCtx = new TaskContext(ctx).accumulate({
449
485
  taskId: task.id,
486
+ stepWriteLock: new Lock(),
450
487
  logger: new TaskLogger(log, this.config.streamBufferSize, this.config.maxLoggingBuffer),
451
488
  attempt: task.attempt,
452
489
  resultCache: { "task.attempt": task.attempt },
@@ -668,47 +705,30 @@ export class TaskEngine extends AbsContextual {
668
705
  let steps = this.normalizeSteps(task.steps);
669
706
  let idx = task.currentStep ?? 0;
670
707
  const results = this.normalizeStepResults(task.stepResults);
708
+ const maxConcurrentSteps = this.getCompositeStepConcurrencyLimit();
709
+ const canBatchConcurrentSteps = maxConcurrentSteps > 1;
671
710
  const cacheResult = (key, value) => {
672
711
  context.cacheResult(key, value);
673
712
  if (ctx instanceof TaskContext && ctx !== context) {
674
713
  ctx.cacheResult(key, value);
675
714
  }
676
715
  };
677
- for (let i = 0; i < results.length; i += 1) {
678
- const existing = results[i];
679
- if (existing?.status === TaskStatus.SUCCEEDED) {
680
- const prevStep = steps[i];
681
- if (!prevStep)
682
- continue;
683
- const cacheKey = `${task.id}:step:${i}`;
684
- cacheResult(prevStep.classification, existing.output);
685
- cacheResult(cacheKey, existing.output);
686
- }
687
- }
688
- while (idx < steps.length) {
689
- context.setStep(idx);
690
- const step = steps[idx];
691
- const handler = this.registry.get(step.classification);
692
- if (!handler)
693
- throw new Error(`No task handler registered for composite step: ${step.classification}`);
694
- const dependencies = this.normalizeDependencies(step.dependsOn);
695
- const dependenciesSatisfied = await this.areDependenciesSatisfied(dependencies, context);
696
- if (!dependenciesSatisfied) {
697
- context.reschedule(new Date(Date.now() + this.config.pollMsIdle), `Waiting dependencies for step ${idx} (${step.classification})`);
698
- }
699
- const lockConflict = await this.hasLockConflict(task, idx, context);
700
- if (lockConflict) {
701
- context.reschedule(new Date(Date.now() + this.config.pollMsIdle), `Waiting lock for step ${idx} (${step.classification})`);
716
+ const refreshFromTask = () => {
717
+ steps = this.normalizeSteps(task.steps);
718
+ for (let i = 0; i < results.length; i += 1) {
719
+ const existing = results[i];
720
+ if (existing?.status === TaskStatus.SUCCEEDED) {
721
+ const prevStep = steps[i];
722
+ if (!prevStep)
723
+ continue;
724
+ const cacheKey = `${task.id}:step:${i}`;
725
+ cacheResult(prevStep.classification, existing.output);
726
+ cacheResult(cacheKey, existing.output);
727
+ }
702
728
  }
703
- task.currentStep = idx;
704
- const persistedCurrent = await this.tasks.update(task);
705
- Object.assign(task, persistedCurrent);
706
- await context.progress({
707
- currentStep: idx,
708
- totalSteps: steps.length,
709
- });
710
- const stepIndex = idx;
711
- context.cache.put("scheduleCompositeSteps", async (newSteps, ctx) => {
729
+ };
730
+ const scheduleCompositeSteps = (stepIndex, taskStepContext) => {
731
+ taskStepContext.cache.put("scheduleCompositeSteps", async (newSteps, ctx) => {
712
732
  const log = ctx.logger.for("scheduleSteps.afterCurrent");
713
733
  const normalizedNewSteps = this.normalizeSteps(newSteps);
714
734
  if (!normalizedNewSteps.length)
@@ -719,7 +739,7 @@ export class TaskEngine extends AbsContextual {
719
739
  task.steps = currentSteps;
720
740
  const persisted = await this.tasks.update(task, context);
721
741
  Object.assign(task, persisted);
722
- steps = this.normalizeSteps(task.steps);
742
+ refreshFromTask();
723
743
  log.verbose(`Inserted ${normalizedNewSteps.length} steps at index ${insertionIndex}`);
724
744
  const updateEvent = await this.persistEvent(context, task.id, TaskEventType.UPDATE, {
725
745
  status: "update",
@@ -732,7 +752,7 @@ export class TaskEngine extends AbsContextual {
732
752
  });
733
753
  this.bus.emit(updateEvent, context);
734
754
  });
735
- context.cache.put("scheduleCompositeStepsAtEnd", async (newSteps, ctx) => {
755
+ taskStepContext.cache.put("scheduleCompositeStepsAtEnd", async (newSteps, ctx) => {
736
756
  const log = ctx.logger.for("scheduleSteps.atEnd");
737
757
  const normalizedNewSteps = this.normalizeSteps(newSteps);
738
758
  if (!normalizedNewSteps.length)
@@ -743,7 +763,7 @@ export class TaskEngine extends AbsContextual {
743
763
  task.steps = currentSteps;
744
764
  const persisted = await this.tasks.update(task, context);
745
765
  Object.assign(task, persisted);
746
- steps = this.normalizeSteps(task.steps);
766
+ refreshFromTask();
747
767
  log.verbose(`Appended ${normalizedNewSteps.length} steps at tail (index ${insertionIndex})`);
748
768
  const updateEvent = await this.persistEvent(context, task.id, TaskEventType.UPDATE, {
749
769
  status: "update",
@@ -756,18 +776,44 @@ export class TaskEngine extends AbsContextual {
756
776
  });
757
777
  this.bus.emit(updateEvent, context);
758
778
  });
759
- await context.pipe([
779
+ };
780
+ const runSingleStep = async (stepIndex) => {
781
+ const step = steps[stepIndex];
782
+ const handler = this.registry.get(step.classification);
783
+ if (!handler) {
784
+ throw new Error(`No task handler registered for composite step: ${step.classification}`);
785
+ }
786
+ const taskStepContext = this.createCompositeStepContext(context, stepIndex);
787
+ scheduleCompositeSteps(stepIndex, taskStepContext);
788
+ const dependencies = this.normalizeDependencies(step.dependsOn);
789
+ const dependenciesSatisfied = await this.areDependenciesSatisfied(dependencies, taskStepContext);
790
+ if (!dependenciesSatisfied) {
791
+ taskStepContext.reschedule(new Date(Date.now() + this.config.pollMsIdle), `Waiting dependencies for step ${stepIndex} (${step.classification})`);
792
+ }
793
+ const lockConflict = await this.hasLockConflict(task, stepIndex, taskStepContext);
794
+ if (lockConflict) {
795
+ taskStepContext.reschedule(new Date(Date.now() + this.config.pollMsIdle), `Waiting lock for step ${stepIndex} (${step.classification})`);
796
+ }
797
+ await this.withStepWriteLock(taskStepContext, async () => {
798
+ task.currentStep = stepIndex;
799
+ const persistedCurrent = await this.tasks.update(task, context);
800
+ Object.assign(task, persistedCurrent);
801
+ });
802
+ await taskStepContext.progress({
803
+ currentStep: stepIndex,
804
+ totalSteps: steps.length,
805
+ });
806
+ await taskStepContext.pipe([
760
807
  LogLevel.info,
761
- `Composite step ${idx + 1}/${steps.length}: ${step.classification}`,
808
+ `Composite step ${stepIndex + 1}/${steps.length}: ${step.classification}`,
762
809
  ]);
763
810
  const stepMaxAttempts = step.maxAttempts ?? 1;
764
811
  let stepAttempt = 0;
765
812
  let lastStepErr;
766
813
  while (stepAttempt < stepMaxAttempts) {
767
814
  try {
768
- const out = await handler.run(step.input, context);
769
- // Ensure step-tagged logs are flushed before advancing the step pointer.
770
- await context.flush();
815
+ const out = await handler.run(step.input, taskStepContext);
816
+ await taskStepContext.flush();
771
817
  const now = new Date();
772
818
  results[stepIndex] = new TaskStepResultModel({
773
819
  status: TaskStatus.SUCCEEDED,
@@ -779,13 +825,14 @@ export class TaskEngine extends AbsContextual {
779
825
  const cacheKey = `${task.id}:step:${stepIndex}`;
780
826
  cacheResult(step.classification, out);
781
827
  cacheResult(cacheKey, out);
782
- idx = stepIndex + 1;
783
- task.stepResults = results;
784
- task.currentStep = idx;
785
- const persisted = await this.tasks.update(task);
786
- Object.assign(task, persisted);
787
- await this.emitProgress(context, task.id, {
788
- currentStep: idx,
828
+ await this.withStepWriteLock(taskStepContext, async () => {
829
+ task.stepResults = results;
830
+ task.currentStep = this.recalculateCompositeCurrentStep(steps, results);
831
+ const persisted = await this.tasks.update(task, context);
832
+ Object.assign(task, persisted);
833
+ });
834
+ await this.emitProgress(taskStepContext, task.id, {
835
+ currentStep: task.currentStep ?? stepIndex + 1,
789
836
  totalSteps: steps.length,
790
837
  output: out,
791
838
  });
@@ -793,14 +840,14 @@ export class TaskEngine extends AbsContextual {
793
840
  break;
794
841
  }
795
842
  catch (err) {
796
- stepAttempt++;
843
+ stepAttempt += 1;
797
844
  lastStepErr = err;
798
845
  if (stepAttempt < stepMaxAttempts) {
799
846
  const stepBackoff = this.normalizeBackoff(step.backoff ?? task.backoff);
800
847
  const delay = computeBackoffMs(stepAttempt, stepBackoff);
801
- await context.pipe(LogLevel.warn, `Composite step ${idx} attempt ${stepAttempt}/${stepMaxAttempts} failed, retrying in ${delay}ms`, { classification: step.classification, attempt: stepAttempt, delay });
848
+ await taskStepContext.pipe(LogLevel.warn, `Composite step ${stepIndex} attempt ${stepAttempt}/${stepMaxAttempts} failed, retrying in ${delay}ms`, { classification: step.classification, attempt: stepAttempt, delay });
802
849
  await sleep(delay);
803
- await context.heartbeat();
850
+ await taskStepContext.heartbeat();
804
851
  }
805
852
  }
806
853
  }
@@ -808,7 +855,7 @@ export class TaskEngine extends AbsContextual {
808
855
  const now = new Date();
809
856
  const canFail = step.canFail === true;
810
857
  const serializedErr = serializeError(lastStepErr);
811
- results[idx] = new TaskStepResultModel({
858
+ results[stepIndex] = new TaskStepResultModel({
812
859
  status: TaskStatus.FAILED,
813
860
  error: serializedErr,
814
861
  attempt: stepAttempt,
@@ -817,7 +864,7 @@ export class TaskEngine extends AbsContextual {
817
864
  });
818
865
  if (canFail) {
819
866
  try {
820
- await handler.catch?.(step.input, lastStepErr, context);
867
+ await handler.catch?.(step.input, lastStepErr, taskStepContext);
821
868
  }
822
869
  catch (catchErr) {
823
870
  ctx.logger.warn("composite step catch() hook failed", {
@@ -825,22 +872,52 @@ export class TaskEngine extends AbsContextual {
825
872
  });
826
873
  }
827
874
  }
828
- task.stepResults = results;
829
- task.error = canFail ? undefined : serializedErr;
830
- if (canFail) {
831
- idx = stepIndex + 1;
832
- task.currentStep = idx;
833
- }
834
- else {
835
- task.currentStep = idx;
836
- }
837
- // persist composite progress before optionally continuing to the next step
838
- const persisted = await this.tasks.update(task);
839
- Object.assign(task, persisted);
875
+ await this.withStepWriteLock(taskStepContext, async () => {
876
+ task.stepResults = results;
877
+ task.error = canFail ? undefined : serializedErr;
878
+ task.currentStep = this.recalculateCompositeCurrentStep(steps, results);
879
+ const persisted = await this.tasks.update(task, context);
880
+ Object.assign(task, persisted);
881
+ });
840
882
  if (!canFail) {
841
883
  throw lastStepErr;
842
884
  }
843
885
  }
886
+ };
887
+ const runConcurrentBatch = async (indices) => {
888
+ const batch = indices.map((stepIndex) => runSingleStep(stepIndex));
889
+ const settled = await Promise.allSettled(batch);
890
+ const hardFailure = settled.find((result) => result.status === "rejected");
891
+ if (hardFailure && hardFailure.status === "rejected") {
892
+ throw hardFailure.reason;
893
+ }
894
+ };
895
+ refreshFromTask();
896
+ while (idx < steps.length) {
897
+ const step = steps[idx];
898
+ if (this.isConcurrentCompositeStep(step) && canBatchConcurrentSteps) {
899
+ const batchLock = step.lock;
900
+ const batchIndices = [idx];
901
+ for (let cursor = idx + 1; cursor < steps.length && batchIndices.length < maxConcurrentSteps; cursor += 1) {
902
+ const candidate = steps[cursor];
903
+ if (!this.isConcurrentCompositeStep(candidate))
904
+ break;
905
+ if (candidate.lock !== batchLock)
906
+ break;
907
+ if (candidate.dependsOn?.length)
908
+ break;
909
+ batchIndices.push(cursor);
910
+ }
911
+ if (batchIndices.length > 1) {
912
+ await runConcurrentBatch(batchIndices);
913
+ steps = this.normalizeSteps(task.steps);
914
+ idx = this.recalculateCompositeCurrentStep(steps, results);
915
+ continue;
916
+ }
917
+ }
918
+ await runSingleStep(idx);
919
+ steps = this.normalizeSteps(task.steps);
920
+ idx = this.recalculateCompositeCurrentStep(steps, results);
844
921
  }
845
922
  return { stepResults: results };
846
923
  }
@@ -938,10 +1015,12 @@ export class TaskEngine extends AbsContextual {
938
1015
  step,
939
1016
  });
940
1017
  });
941
- const nextTail = [...(task.logTail ?? []), ...entries].slice(-this.config.logTailMax);
942
- task.logTail = nextTail;
943
1018
  try {
944
- return [await this.tasks.update(task, ctx), entries];
1019
+ return await this.withStepWriteLock(ctx, async () => {
1020
+ const nextTail = [...(task.logTail ?? []), ...entries].slice(-this.config.logTailMax);
1021
+ task.logTail = nextTail;
1022
+ return [await this.tasks.update(task, ctx), entries];
1023
+ });
945
1024
  }
946
1025
  catch {
947
1026
  return [task, []];