Skip to content

Commit 1fa12bd

Browse files
javannajasontedor
authored andcommitted
Replace failure.get().addSuppressed with failure.accumulateAndGet() (#37649)
Also add a test for concurrent incoming failures
1 parent 68b6f4d commit 1fa12bd

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed

server/src/main/java/org/elasticsearch/action/support/GroupedActionListener.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ public void onResponse(T element) {
7272
@Override
7373
public void onFailure(Exception e) {
7474
if (failure.compareAndSet(null, e) == false) {
75-
failure.get().addSuppressed(e);
75+
failure.accumulateAndGet(e, (previous, current) -> {
76+
previous.addSuppressed(current);
77+
return previous;
78+
});
7679
}
7780
if (countDown.countDown()) {
7881
delegate.onFailure(failure.get());

server/src/test/java/org/elasticsearch/action/support/GroupedActionListenerTests.java

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@
2626
import java.util.Collection;
2727
import java.util.Collections;
2828
import java.util.concurrent.CyclicBarrier;
29+
import java.util.concurrent.ExecutorService;
30+
import java.util.concurrent.Executors;
2931
import java.util.concurrent.TimeUnit;
3032
import java.util.concurrent.atomic.AtomicInteger;
3133
import java.util.concurrent.atomic.AtomicReference;
3234

35+
import static org.hamcrest.CoreMatchers.instanceOf;
36+
3337
public class GroupedActionListenerTests extends ESTestCase {
3438

3539
public void testNotifications() throws InterruptedException {
@@ -55,20 +59,17 @@ public void onFailure(Exception e) {
5559
Thread[] threads = new Thread[numThreads];
5660
CyclicBarrier barrier = new CyclicBarrier(numThreads);
5761
for (int i = 0; i < numThreads; i++) {
58-
threads[i] = new Thread() {
59-
@Override
60-
public void run() {
61-
try {
62-
barrier.await(10, TimeUnit.SECONDS);
63-
} catch (Exception e) {
64-
throw new AssertionError(e);
65-
}
66-
int c = 0;
67-
while((c = count.incrementAndGet()) <= groupSize) {
68-
listener.onResponse(c-1);
69-
}
62+
threads[i] = new Thread(() -> {
63+
try {
64+
barrier.await(10, TimeUnit.SECONDS);
65+
} catch (Exception e) {
66+
throw new AssertionError(e);
67+
}
68+
int c = 0;
69+
while((c = count.incrementAndGet()) <= groupSize) {
70+
listener.onResponse(c-1);
7071
}
71-
};
72+
});
7273
threads[i].start();
7374
}
7475
for (Thread t : threads) {
@@ -100,11 +101,9 @@ public void onFailure(Exception e) {
100101
excRef.set(e);
101102
}
102103
};
103-
Collection<Integer> defaults = randomBoolean() ? Collections.singletonList(-1) :
104-
Collections.emptyList();
104+
Collection<Integer> defaults = randomBoolean() ? Collections.singletonList(-1) : Collections.emptyList();
105105
int size = randomIntBetween(3, 4);
106-
GroupedActionListener<Integer> listener = new GroupedActionListener<>(result, size,
107-
defaults);
106+
GroupedActionListener<Integer> listener = new GroupedActionListener<>(result, size, defaults);
108107
listener.onResponse(0);
109108
IOException ioException = new IOException();
110109
RuntimeException rtException = new RuntimeException();
@@ -121,4 +120,23 @@ public void onFailure(Exception e) {
121120
listener.onResponse(1);
122121
assertNull(resRef.get());
123122
}
123+
124+
public void testConcurrentFailures() throws InterruptedException {
125+
AtomicReference<Exception> finalException = new AtomicReference<>();
126+
int numGroups = randomIntBetween(10, 100);
127+
GroupedActionListener<Void> listener = new GroupedActionListener<>(
128+
ActionListener.wrap(r -> {}, finalException::set), numGroups, Collections.emptyList());
129+
ExecutorService executorService = Executors.newFixedThreadPool(numGroups);
130+
for (int i = 0; i < numGroups; i++) {
131+
executorService.submit(() -> listener.onFailure(new IOException()));
132+
}
133+
134+
executorService.shutdown();
135+
executorService.awaitTermination(10, TimeUnit.SECONDS);
136+
137+
Exception exception = finalException.get();
138+
assertNotNull(exception);
139+
assertThat(exception, instanceOf(IOException.class));
140+
assertEquals(numGroups - 1, exception.getSuppressed().length);
141+
}
124142
}

0 commit comments

Comments
 (0)