19
19
20
20
package org .elasticsearch .common .util .concurrent ;
21
21
22
+ import org .apache .logging .log4j .message .ParameterizedMessage ;
22
23
import org .elasticsearch .action .ActionListener ;
23
24
import org .elasticsearch .common .settings .Settings ;
24
25
import org .elasticsearch .test .ESTestCase ;
30
31
import java .util .concurrent .ExecutorService ;
31
32
import java .util .concurrent .atomic .AtomicInteger ;
32
33
34
+ import static org .hamcrest .Matchers .is ;
35
+
33
36
public class ListenableFutureTests extends ESTestCase {
34
37
35
38
private ExecutorService executorService ;
39
+ private ThreadContext threadContext = new ThreadContext (Settings .EMPTY );
36
40
37
41
@ After
38
42
public void stopExecutorService () throws InterruptedException {
@@ -46,7 +50,7 @@ public void testListenableFutureNotifiesListeners() {
46
50
AtomicInteger notifications = new AtomicInteger (0 );
47
51
final int numberOfListeners = scaledRandomIntBetween (1 , 12 );
48
52
for (int i = 0 ; i < numberOfListeners ; i ++) {
49
- future .addListener (ActionListener .wrap (notifications ::incrementAndGet ), EsExecutors .newDirectExecutorService ());
53
+ future .addListener (ActionListener .wrap (notifications ::incrementAndGet ), EsExecutors .newDirectExecutorService (), threadContext );
50
54
}
51
55
52
56
future .onResponse ("" );
@@ -63,7 +67,7 @@ public void testListenableFutureNotifiesListenersOnException() {
63
67
future .addListener (ActionListener .wrap (s -> fail ("this should never be called" ), e -> {
64
68
assertEquals (exception , e );
65
69
notifications .incrementAndGet ();
66
- }), EsExecutors .newDirectExecutorService ());
70
+ }), EsExecutors .newDirectExecutorService (), threadContext );
67
71
}
68
72
69
73
future .onFailure (exception );
@@ -76,7 +80,7 @@ public void testConcurrentListenerRegistrationAndCompletion() throws BrokenBarri
76
80
final int completingThread = randomIntBetween (0 , numberOfThreads - 1 );
77
81
final ListenableFuture <String > future = new ListenableFuture <>();
78
82
executorService = EsExecutors .newFixed ("testConcurrentListenerRegistrationAndCompletion" , numberOfThreads , 1000 ,
79
- EsExecutors .daemonThreadFactory ("listener" ), new ThreadContext ( Settings . EMPTY ) );
83
+ EsExecutors .daemonThreadFactory ("listener" ), threadContext );
80
84
final CyclicBarrier barrier = new CyclicBarrier (1 + numberOfThreads );
81
85
final CountDownLatch listenersLatch = new CountDownLatch (numberOfThreads - 1 );
82
86
final AtomicInteger numResponses = new AtomicInteger (0 );
@@ -85,20 +89,31 @@ public void testConcurrentListenerRegistrationAndCompletion() throws BrokenBarri
85
89
for (int i = 0 ; i < numberOfThreads ; i ++) {
86
90
final int threadNum = i ;
87
91
Thread thread = new Thread (() -> {
92
+ threadContext .putTransient ("key" , threadNum );
88
93
try {
89
94
barrier .await ();
90
95
if (threadNum == completingThread ) {
96
+ // we need to do more than just call onResponse as this often results in synchronous
97
+ // execution of the listeners instead of actually going async
98
+ final int waitTime = randomIntBetween (0 , 50 );
99
+ Thread .sleep (waitTime );
100
+ logger .info ("completing the future after sleeping {}ms" , waitTime );
91
101
future .onResponse ("" );
102
+ logger .info ("future received response" );
92
103
} else {
104
+ logger .info ("adding listener {}" , threadNum );
93
105
future .addListener (ActionListener .wrap (s -> {
106
+ logger .info ("listener {} received value {}" , threadNum , s );
94
107
assertEquals ("" , s );
108
+ assertThat (threadContext .getTransient ("key" ), is (threadNum ));
95
109
numResponses .incrementAndGet ();
96
110
listenersLatch .countDown ();
97
111
}, e -> {
98
- logger .error (" caught unexpected exception" , e );
112
+ logger .error (new ParameterizedMessage ( "listener {} caught unexpected exception", threadNum ) , e );
99
113
numExceptions .incrementAndGet ();
100
114
listenersLatch .countDown ();
101
- }), executorService );
115
+ }), executorService , threadContext );
116
+ logger .info ("listener {} added" , threadNum );
102
117
}
103
118
barrier .await ();
104
119
} catch (InterruptedException | BrokenBarrierException e ) {
0 commit comments