3434import org .elasticsearch .core .TimeValue ;
3535import org .elasticsearch .index .IndexNotFoundException ;
3636import org .elasticsearch .node .NodeClosedException ;
37+ import org .elasticsearch .tasks .CancellableTask ;
3738import org .elasticsearch .tasks .Task ;
3839import org .elasticsearch .threadpool .ThreadPool ;
3940import org .elasticsearch .transport .TransportService ;
@@ -91,28 +92,42 @@ protected void masterOperation(
9192 final ClusterState unusedState ,
9293 final ActionListener <ClusterHealthResponse > listener
9394 ) {
95+ assert task instanceof CancellableTask ;
96+ final CancellableTask cancellableTask = (CancellableTask ) task ;
9497
9598 final int waitCount = getWaitCount (request );
9699
97100 if (request .waitForEvents () != null ) {
98- waitForEventsAndExecuteHealth (request , listener , waitCount , threadPool .relativeTimeInMillis () + request .timeout ().millis ());
101+ waitForEventsAndExecuteHealth (
102+ cancellableTask ,
103+ request ,
104+ listener ,
105+ waitCount ,
106+ threadPool .relativeTimeInMillis () + request .timeout ().millis ()
107+ );
99108 } else {
100109 executeHealth (
110+ cancellableTask ,
101111 request ,
102112 clusterService .state (),
103113 listener ,
104114 waitCount ,
105- clusterState -> listener . onResponse ( getResponse ( request , clusterState , waitCount , TimeoutState .OK ) )
115+ clusterState -> sendResponse ( cancellableTask , request , clusterState , waitCount , TimeoutState .OK , listener )
106116 );
107117 }
108118 }
109119
110120 private void waitForEventsAndExecuteHealth (
121+ final CancellableTask task ,
111122 final ClusterHealthRequest request ,
112123 final ActionListener <ClusterHealthResponse > listener ,
113124 final int waitCount ,
114125 final long endTimeRelativeMillis
115126 ) {
127+ if (task .notifyIfCancelled (listener )) {
128+ return ;
129+ }
130+
116131 assert request .waitForEvents () != null ;
117132 if (request .local ()) {
118133 clusterService .submitStateUpdateTask (
@@ -129,11 +144,12 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS
129144 final TimeValue newTimeout = TimeValue .timeValueMillis (timeoutInMillis );
130145 request .timeout (newTimeout );
131146 executeHealth (
147+ task ,
132148 request ,
133149 clusterService .state (),
134150 listener ,
135151 waitCount ,
136- observedState -> waitForEventsAndExecuteHealth (request , listener , waitCount , endTimeRelativeMillis )
152+ observedState -> waitForEventsAndExecuteHealth (task , request , listener , waitCount , endTimeRelativeMillis )
137153 );
138154 }
139155
@@ -166,11 +182,12 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS
166182 assert newState .stateUUID ().equals (appliedState .stateUUID ())
167183 : newState .stateUUID () + " vs " + appliedState .stateUUID ();
168184 executeHealth (
185+ task ,
169186 request ,
170187 appliedState ,
171188 listener ,
172189 waitCount ,
173- observedState -> waitForEventsAndExecuteHealth (request , listener , waitCount , endTimeRelativeMillis )
190+ observedState -> waitForEventsAndExecuteHealth (task , request , listener , waitCount , endTimeRelativeMillis )
174191 );
175192 }
176193
@@ -187,7 +204,7 @@ public void onNoLongerMaster(String source) {
187204 @ Override
188205 public void onFailure (String source , Exception e ) {
189206 if (e instanceof ProcessClusterEventTimeoutException ) {
190- listener . onResponse ( getResponse ( request , clusterService .state (), waitCount , TimeoutState .TIMED_OUT ) );
207+ sendResponse ( task , request , clusterService .state (), waitCount , TimeoutState .TIMED_OUT , listener );
191208 } else {
192209 logger .error (() -> new ParameterizedMessage ("unexpected failure during [{}]" , source ), e );
193210 listener .onFailure (e );
@@ -199,21 +216,25 @@ public void onFailure(String source, Exception e) {
199216 }
200217
201218 private void executeHealth (
219+ final CancellableTask task ,
202220 final ClusterHealthRequest request ,
203221 final ClusterState currentState ,
204222 final ActionListener <ClusterHealthResponse > listener ,
205223 final int waitCount ,
206224 final Consumer <ClusterState > onNewClusterStateAfterDelay
207225 ) {
226+ if (task .notifyIfCancelled (listener )) {
227+ return ;
228+ }
208229
209230 if (request .timeout ().millis () == 0 ) {
210- listener . onResponse ( getResponse ( request , currentState , waitCount , TimeoutState .ZERO_TIMEOUT ) );
231+ sendResponse ( task , request , currentState , waitCount , TimeoutState .ZERO_TIMEOUT , listener );
211232 return ;
212233 }
213234
214235 final Predicate <ClusterState > validationPredicate = newState -> validateRequest (request , newState , waitCount );
215236 if (validationPredicate .test (currentState )) {
216- listener . onResponse ( getResponse ( request , currentState , waitCount , TimeoutState .OK ) );
237+ sendResponse ( task , request , currentState , waitCount , TimeoutState .OK , listener );
217238 } else {
218239 final ClusterStateObserver observer = new ClusterStateObserver (
219240 currentState ,
@@ -235,7 +256,7 @@ public void onClusterServiceClose() {
235256
236257 @ Override
237258 public void onTimeout (TimeValue timeout ) {
238- listener . onResponse ( getResponse ( request , observer .setAndGetObservedState (), waitCount , TimeoutState .TIMED_OUT ) );
259+ sendResponse ( task , request , observer .setAndGetObservedState (), waitCount , TimeoutState .TIMED_OUT , listener );
239260 }
240261 };
241262 observer .waitForNextChange (stateListener , validationPredicate , request .timeout ());
@@ -282,27 +303,32 @@ private enum TimeoutState {
282303 ZERO_TIMEOUT
283304 }
284305
285- private ClusterHealthResponse getResponse (
306+ private void sendResponse (
307+ final CancellableTask task ,
286308 final ClusterHealthRequest request ,
287- ClusterState clusterState ,
309+ final ClusterState clusterState ,
288310 final int waitFor ,
289- TimeoutState timeoutState
311+ final TimeoutState timeoutState ,
312+ final ActionListener <ClusterHealthResponse > listener
290313 ) {
291- ClusterHealthResponse response = clusterHealth (
292- request ,
293- clusterState ,
294- clusterService .getMasterService ().numberOfPendingTasks (),
295- allocationService .getNumberOfInFlightFetches (),
296- clusterService .getMasterService ().getMaxTaskWaitTime ()
297- );
298- int readyCounter = prepareResponse (request , response , clusterState , indexNameExpressionResolver );
299- boolean valid = (readyCounter == waitFor );
300- assert valid || (timeoutState != TimeoutState .OK );
301- // If valid && timeoutState == TimeoutState.ZERO_TIMEOUT then we immediately found **and processed** a valid state, so we don't
302- // consider this a timeout. However if timeoutState == TimeoutState.TIMED_OUT then we didn't process a valid state (perhaps we
303- // failed on wait_for_events) so this does count as a timeout.
304- response .setTimedOut (valid == false || timeoutState == TimeoutState .TIMED_OUT );
305- return response ;
314+ ActionListener .completeWith (listener , () -> {
315+ task .ensureNotCancelled ();
316+ ClusterHealthResponse response = clusterHealth (
317+ request ,
318+ clusterState ,
319+ clusterService .getMasterService ().numberOfPendingTasks (),
320+ allocationService .getNumberOfInFlightFetches (),
321+ clusterService .getMasterService ().getMaxTaskWaitTime ()
322+ );
323+ int readyCounter = prepareResponse (request , response , clusterState , indexNameExpressionResolver );
324+ boolean valid = (readyCounter == waitFor );
325+ assert valid || (timeoutState != TimeoutState .OK );
326+ // If valid && timeoutState == TimeoutState.ZERO_TIMEOUT then we immediately found **and processed** a valid state, so we don't
327+ // consider this a timeout. However if timeoutState == TimeoutState.TIMED_OUT then we didn't process a valid state (perhaps we
328+ // failed on wait_for_events) so this does count as a timeout.
329+ response .setTimedOut (valid == false || timeoutState == TimeoutState .TIMED_OUT );
330+ return response ;
331+ });
306332 }
307333
308334 static int prepareResponse (
0 commit comments