1 /* 2 * Copyright 2015 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.cloud; 18 19 import com.google.api.core.ApiClock; 20 import com.google.api.core.BetaApi; 21 import com.google.api.gax.retrying.DirectRetryingExecutor; 22 import com.google.api.gax.retrying.ExponentialPollAlgorithm; 23 import com.google.api.gax.retrying.ExponentialRetryAlgorithm; 24 import com.google.api.gax.retrying.ResultRetryAlgorithm; 25 import com.google.api.gax.retrying.RetryAlgorithm; 26 import com.google.api.gax.retrying.RetrySettings; 27 import com.google.api.gax.retrying.RetryingExecutor; 28 import com.google.api.gax.retrying.RetryingFuture; 29 import com.google.api.gax.retrying.TimedRetryAlgorithm; 30 import java.util.concurrent.Callable; 31 import java.util.concurrent.ExecutionException; 32 33 /** 34 * Utility class for retrying operations. For more details about the parameters, see {@link 35 * RetrySettings}. In case if retrying is unsuccessful, {@link RetryHelperException} will be thrown. 36 */ 37 @BetaApi 38 public class RetryHelper { runWithRetries( Callable<V> callable, RetrySettings retrySettings, ResultRetryAlgorithm<?> resultRetryAlgorithm, ApiClock clock)39 public static <V> V runWithRetries( 40 Callable<V> callable, 41 RetrySettings retrySettings, 42 ResultRetryAlgorithm<?> resultRetryAlgorithm, 43 ApiClock clock) 44 throws RetryHelperException { 45 try { 46 // Suppressing should be ok as a workaraund. Current and only ResultRetryAlgorithm 47 // implementation does not use response at all, so ignoring its type is ok. 48 @SuppressWarnings("unchecked") 49 ResultRetryAlgorithm<V> algorithm = (ResultRetryAlgorithm<V>) resultRetryAlgorithm; 50 return run(callable, new ExponentialRetryAlgorithm(retrySettings, clock), algorithm); 51 } catch (Exception e) { 52 // TODO: remove RetryHelperException, throw InterruptedException or 53 // ExecutionException#getCause() explicitly 54 throw new RetryHelperException(e.getCause()); 55 } 56 } 57 poll( Callable<V> callable, RetrySettings pollSettings, ResultRetryAlgorithm<V> resultPollAlgorithm, ApiClock clock)58 public static <V> V poll( 59 Callable<V> callable, 60 RetrySettings pollSettings, 61 ResultRetryAlgorithm<V> resultPollAlgorithm, 62 ApiClock clock) 63 throws ExecutionException, InterruptedException { 64 return run(callable, new ExponentialPollAlgorithm(pollSettings, clock), resultPollAlgorithm); 65 } 66 run( Callable<V> callable, TimedRetryAlgorithm timedAlgorithm, ResultRetryAlgorithm<V> resultAlgorithm)67 private static <V> V run( 68 Callable<V> callable, 69 TimedRetryAlgorithm timedAlgorithm, 70 ResultRetryAlgorithm<V> resultAlgorithm) 71 throws ExecutionException, InterruptedException { 72 RetryAlgorithm<V> retryAlgorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); 73 RetryingExecutor<V> executor = new DirectRetryingExecutor<>(retryAlgorithm); 74 75 RetryingFuture<V> retryingFuture = executor.createFuture(callable); 76 executor.submit(retryingFuture); 77 return retryingFuture.get(); 78 } 79 80 public static class RetryHelperException extends RuntimeException { 81 82 private static final long serialVersionUID = -8519852520090965314L; 83 RetryHelperException(Throwable cause)84 RetryHelperException(Throwable cause) { 85 super(cause); 86 } 87 } 88 } 89