Skip to content

Commit fbba692

Browse files
rleivancexu
authored andcommitted
Promise.allOf should not block on empty input (#508)
1 parent c07a50b commit fbba692

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

src/main/java/com/uber/cadence/internal/sync/AllOfFuture.java

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.uber.cadence.workflow.Workflow;
2424
import java.util.Arrays;
2525
import java.util.Collection;
26+
import java.util.Collections;
2627
import java.util.List;
2728
import java.util.concurrent.TimeUnit;
2829
import java.util.concurrent.TimeoutException;
@@ -34,25 +35,22 @@ class AllOfPromise<G> implements Promise<List<G>> {
3435

3536
private int notReadyCount;
3637

37-
@SuppressWarnings("unchecked")
3838
AllOfPromise(Promise<G>[] promises) {
39-
// Using array to initialize it to the desired size with nulls.
40-
result = (G[]) new Object[promises.length];
41-
int index = 0;
42-
for (Promise<G> f : promises) {
43-
addPromise(index, f);
44-
index++;
45-
}
39+
this(Arrays.asList(promises));
4640
}
4741

4842
@SuppressWarnings("unchecked")
4943
public AllOfPromise(Collection<Promise<G>> promises) {
50-
// Using array to initialize it to the desired size with nulls.
51-
result = (G[]) new Object[promises.size()];
52-
int index = 0;
53-
for (Promise<G> f : promises) {
54-
addPromise(index, f);
55-
index++;
44+
if (promises.isEmpty()) {
45+
impl.complete(Collections.emptyList());
46+
} else {
47+
// Using array to initialize it to the desired size with nulls.
48+
result = (G[]) new Object[promises.size()];
49+
int index = 0;
50+
for (Promise<G> f : promises) {
51+
addPromise(index, f);
52+
index++;
53+
}
5654
}
5755
}
5856

src/test/java/com/uber/cadence/internal/sync/PromiseTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package com.uber.cadence.internal.sync;
1919

20+
import static java.util.Collections.emptyList;
2021
import static org.junit.Assert.assertEquals;
2122
import static org.junit.Assert.assertFalse;
2223
import static org.junit.Assert.assertTrue;
@@ -438,6 +439,36 @@ public void testAllOf() throws Throwable {
438439
trace.setExpected(expected);
439440
}
440441

442+
@Test
443+
public void testAllOf_shouldCompleteWithoutBlocking() throws Throwable {
444+
DeterministicRunner r =
445+
DeterministicRunner.newRunner(
446+
() -> {
447+
Promise<List<String>> allOf = Promise.allOf(emptyList());
448+
449+
assertTrue(allOf.isCompleted());
450+
451+
Promise<Boolean> thenApply =
452+
allOf.thenApply(result -> result.isEmpty() ? Boolean.TRUE : Boolean.FALSE);
453+
assertTrue(thenApply.isCompleted());
454+
assertTrue(thenApply.get());
455+
456+
assertTrue(allOf.get().isEmpty());
457+
trace.add("done1");
458+
459+
@SuppressWarnings({"unchecked", "rawtypes"})
460+
AllOfPromise<String> allOfEmptyArray = new AllOfPromise<>(new Promise[0]);
461+
462+
assertTrue(allOfEmptyArray.isCompleted());
463+
assertTrue(allOfEmptyArray.get().isEmpty());
464+
trace.add("done2");
465+
});
466+
467+
r.runUntilAllBlocked();
468+
trace.setExpected("done1", "done2");
469+
trace.assertExpected();
470+
}
471+
441472
@Test
442473
public void testAnyOf() throws Throwable {
443474
DeterministicRunner r =

0 commit comments

Comments
 (0)