Invoker { @Retries.RetryTranslated public void retry(String action, String path, boolean idempotent, Retried retrying, VoidOperation operation) throws IOException { retry(action, path, idempotent, retrying, () -> { operation.execute(); return null; }); } Invoker(
      RetryPolicy retryPolicy,
      Retried retryCallback); RetryPolicy getRetryPolicy(); Retried getRetryCallback(); @Retries.OnceTranslated static T once(String action, String path, Operation<T> operation); @Retries.OnceTranslated static void once(String action, String path, VoidOperation operation); static void ignoreIOExceptions(
      Logger log,
      String action,
      String path,
      Operation<T> operation); static void ignoreIOExceptions(
      Logger log,
      String action,
      String path,
      VoidOperation operation); @Retries.RetryTranslated void retry(String action,
      String path,
      boolean idempotent,
      Retried retrying,
      VoidOperation operation); @Retries.RetryTranslated void retry(String action,
      String path,
      boolean idempotent,
      VoidOperation operation); @Retries.RetryTranslated T retry(String action,
      @Nullable String path,
      boolean idempotent,
      Operation<T> operation); @Retries.RetryTranslated T retry(
      String action,
      @Nullable String path,
      boolean idempotent,
      Retried retrying,
      Operation<T> operation); @Retries.RetryRaw T retryUntranslated(
      String text,
      boolean idempotent,
      Operation<T> operation); @Retries.RetryRaw T retryUntranslated(
      String text,
      boolean idempotent,
      Retried retrying,
      Operation<T> operation); static void quietly(String action,
      String path,
      VoidOperation operation); static Optional<T> quietlyEval(String action,
      String path,
      Operation<T> operation); static final Retried NO_OP; static final Retried LOG_EVENT; }
@Test public void testRetryOnThrottle() throws Throwable { final AtomicInteger counter = new AtomicInteger(0); invoker.retry("test", null, false, () -> { if (counter.incrementAndGet() < 5) { throw newThrottledException(); } }); }
@Test(expected = AWSBadRequestException.class) public void testNoRetryOfBadRequestNonIdempotent() throws Throwable { invoker.retry("test", null, false, () -> { throw serviceException(400, "bad request"); }); }
@Test public void testRetryAWSConnectivity() throws Throwable { final AtomicInteger counter = new AtomicInteger(0); invoker.retry("test", null, false, () -> { if (counter.incrementAndGet() < ACTIVE_RETRY_LIMIT) { throw CLIENT_TIMEOUT_EXCEPTION; } }); assertEquals(ACTIVE_RETRY_LIMIT, counter.get()); }
@Test(expected = AWSBadRequestException.class) public void testRetryBadRequestNotIdempotent() throws Throwable { invoker.retry("test", null, false, () -> { throw BAD_REQUEST; }); }
@Test public void testDynamoDBThrottleConversion() throws Throwable { ProvisionedThroughputExceededException exceededException = new ProvisionedThroughputExceededException("iops"); AWSServiceThrottledException ddb = verifyTranslated( AWSServiceThrottledException.class, exceededException); assertTrue(isThrottleException(exceededException)); assertTrue(isThrottleException(ddb)); assertRetryAction("Expected throttling retry", RETRY_POLICY, RetryPolicy.RetryAction.RETRY, ddb, SAFE_RETRY_COUNT, false); CatchCallback catcher = new CatchCallback(); AtomicBoolean invoked = new AtomicBoolean(false); invoker.retry("test", null, false, catcher, () -> { if (!invoked.getAndSet(true)) { throw exceededException; } }); verifyExceptionClass(AWSServiceThrottledException.class, catcher.lastException); }