Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions packages/durabletask-js/src/task/composite-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import { Task } from "./task";
export class CompositeTask<T> extends Task<T> {
_tasks: Task<any>[] = [];
_completedTasks: number;
_failedTasks: number;

constructor(tasks: Task<any>[]) {
super();

this._tasks = tasks;
this._completedTasks = 0;
this._failedTasks = 0;

for (const task of tasks) {
task._parent = this;
Expand Down
4 changes: 2 additions & 2 deletions packages/durabletask-js/src/task/when-all-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export class WhenAllTask<T> extends CompositeTask<T[]> {
constructor(tasks: Task<T>[]) {
super(tasks);

// Note: Do NOT re-initialize _completedTasks or _failedTasks here.
// CompositeTask's constructor already initializes them to 0 and then
// Note: Do NOT re-initialize _completedTasks here.
// CompositeTask's constructor already initializes it to 0 and then
// processes pre-completed children via onChildCompleted(), which
// increments the counter. Re-initializing would wipe out that count
// and cause the task to hang when some children are already complete.
Expand Down
91 changes: 0 additions & 91 deletions packages/durabletask-js/src/utils/async-pageable.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/durabletask-js/test/when-all-task.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,25 @@ describe("WhenAllTask", () => {
child3.complete(3);
expect(task.pendingTasks()).toBe(0);
});

// Issue #217: failed child completions are counted in the same _completedTasks
// counter as successful ones. There is no separate failed-task counter, so a
// failing child increments completedTasks just like a successful one before
// fail-fast completion kicks in.
it("should count both successful and failed children in completedTasks", () => {
const child1 = new CompletableTask<number>();
const child2 = new CompletableTask<number>();
const child3 = new CompletableTask<number>();
const task = new WhenAllTask([child1, child2, child3]);

child1.complete(1);
expect(task.completedTasks).toBe(1);

// The failing child increments the same counter before fail-fast completes the task.
child2.fail("child failed");

expect(task.completedTasks).toBe(2);
expect(task.isComplete).toBe(true);
expect(task.isFailed).toBe(true);
});
});
21 changes: 21 additions & 0 deletions packages/durabletask-js/test/when-any-task.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,25 @@ describe("WhenAnyTask", () => {
expect(task.isComplete).toBe(false);
expect(task.isFailed).toBe(false);
});

// Issue #217: a failed completion settles WhenAny immediately and is treated the
// same as a successful one — failures are not tracked separately, so a later
// successful child does not override the already-settled failed child.
it("should keep the first failed child as the result even if a later child succeeds", () => {
const child1 = new CompletableTask<number>();
const child2 = new CompletableTask<number>();
const task = new WhenAnyTask([child1, child2]);

child1.fail("first failed");

expect(task.isComplete).toBe(true);
// WhenAny itself is not failed — it simply returns the settled (failed) child.
expect(task.isFailed).toBe(false);
expect(task.getResult()).toBe(child1);

// A subsequent successful completion must not replace the already-settled failed child.
child2.complete(99);
expect(task.getResult()).toBe(child1);
expect(task.getResult().isFailed).toBe(true);
});
});
Loading