/*
* Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.waiters;
import com.amazonaws.*;
import com.amazonaws.annotation.SdkProtectedApi;
import com.amazonaws.util.ValidationUtils;
@SdkProtectedApi
public class WaiterExecution<Input extends AmazonWebServiceRequest, Output> {
/**
* Resource specific function that makes a call to the
* operation specified by the waiter
*/
private final SdkFunction<Input, Output> sdkFunction;
/**
* Represents the input of the operation.
*/
private final Input request;
/**
* List of acceptors defined for each waiter
*/
private final CompositeAcceptor<Output> acceptor;
/**
* Custom polling strategy as given by the end users
*/
private final PollingStrategy pollingStrategy;
/**
* Constructs a new waiter with all the parameters defined
* in the WaiterExecutionBuilder
*
* @param waiterExecutionBuilder Contains all the parameters required to construct a
* new waiter
*/
public WaiterExecution(WaiterExecutionBuilder<Input, Output> waiterExecutionBuilder) {
this.sdkFunction = ValidationUtils.assertNotNull(waiterExecutionBuilder.getSdkFunction(), "sdkFunction");
this.request = ValidationUtils.assertNotNull(waiterExecutionBuilder.getRequest(), "request");
this.acceptor = new CompositeAcceptor<Output>(ValidationUtils.assertNotNull(waiterExecutionBuilder.getAcceptorsList(), "acceptors"));
this.pollingStrategy = ValidationUtils.assertNotNull(waiterExecutionBuilder.getPollingStrategy(), "pollingStrategy");
}
/**
* Polls until a specified resource transitions into either success or failure state or
* until the specified number of retries has been made.
*
* @return True if the resource transitions into desired state.
* @throws AmazonServiceException If the service exception thrown doesn't match any of the expected
* exceptions, it's re-thrown.
* @throws WaiterUnrecoverableException If the resource transitions into a failure/unexpected state.
* @throws WaiterTimedOutException If the resource doesn't transition into the desired state
* even after a certain number of retries.
*/
public boolean pollResource() throws AmazonServiceException, WaiterTimedOutException, WaiterUnrecoverableException {
int retriesAttempted = 0;
while (true) {
switch (getCurrentState()) {
case SUCCESS:
return true;
case FAILURE:
throw new WaiterUnrecoverableException("Resource never entered the desired state as it failed.");
case RETRY:
PollingStrategyContext pollingStrategyContext = new PollingStrategyContext(request, retriesAttempted);
if (pollingStrategy.getRetryStrategy().shouldRetry(pollingStrategyContext)) {
safeCustomDelay(pollingStrategyContext);
retriesAttempted++;
} else {
throw new WaiterTimedOutException("Reached maximum attempts without transitioning to the desired state");
}
break;
}
}
}
/**
* Fetches the current state of the resource based on the acceptor it matches
*
* @return Current state of the resource
* @throws Exception
*/
private WaiterState getCurrentState() throws AmazonServiceException {
try {
return acceptor.accepts(sdkFunction.apply(request));
} catch (AmazonServiceException amazonServiceException) {
return acceptor.accepts(amazonServiceException);
}
}
/**
* Calls the custom delay strategy to control the sleep time
*
* @param pollingStrategyContext Provides the polling strategy context.
* Includes request and number of retries
* attempted so far.
*/
private void safeCustomDelay(PollingStrategyContext pollingStrategyContext) {
try {
pollingStrategy.getDelayStrategy().delayBeforeNextRetry(pollingStrategyContext);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
}