RetryProxy { public static <T> Object create(Class<T> iface, T implementation, RetryPolicy retryPolicy) { return RetryProxy.create(iface, new DefaultFailoverProxyProvider<T>(iface, implementation), retryPolicy); }  static Object create(Class<T> iface, T implementation,
                              RetryPolicy retryPolicy); static Object create(Class<T> iface,
      FailoverProxyProvider<T> proxyProvider, RetryPolicy retryPolicy); static Object create(Class<T> iface, T implementation,
                              Map<String,RetryPolicy> methodNameToPolicyMap); static Object create(Class<T> iface,
      FailoverProxyProvider<T> proxyProvider,
      Map<String, RetryPolicy> methodNameToPolicyMap,
      RetryPolicy defaultPolicy);  }
@Test public void testTryOnceThenFail() throws Exception { RetryPolicy policy = mock(TryOnceThenFail.class); RetryPolicy realPolicy = TRY_ONCE_THEN_FAIL; setupMockPolicy(policy, realPolicy); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, policy); unreliable.alwaysSucceeds(); try { unreliable.failsOnceThenSucceeds(); fail("Should fail"); } catch (UnreliableException e) { verify(policy, times(1)).shouldRetry(any(Exception.class), anyInt(), anyInt(), anyBoolean()); assertEquals(RetryDecision.FAIL, caughtRetryAction.action); assertEquals("try once and fail.", caughtRetryAction.reason); } catch (Exception e) { fail("Other exception other than UnreliableException should also get " + "failed."); } }
@Test public void testRpcInvocation() throws Exception { final UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, RETRY_FOREVER); assertTrue(RetryInvocationHandler.isRpcInvocation(unreliable)); final AtomicInteger count = new AtomicInteger(); ProtocolTranslator xlator = new ProtocolTranslator() { @Override public Object getUnderlyingProxyObject() { count.getAndIncrement(); return unreliable; } }; assertTrue(RetryInvocationHandler.isRpcInvocation(xlator)); assertEquals(1, count.get()); assertFalse(RetryInvocationHandler.isRpcInvocation(new Object())); }
@Test public void testRetryForever() throws UnreliableException { UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, RETRY_FOREVER); unreliable.alwaysSucceeds(); unreliable.failsOnceThenSucceeds(); unreliable.failsTenTimesThenSucceeds(); }
@Test public void testRetryForeverWithFixedSleep() throws UnreliableException { UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create( UnreliableInterface.class, unreliableImpl, retryForeverWithFixedSleep(1, TimeUnit.MILLISECONDS)); unreliable.alwaysSucceeds(); unreliable.failsOnceThenSucceeds(); unreliable.failsTenTimesThenSucceeds(); }
@Test public void testRetryUpToMaximumCountWithFixedSleep() throws Exception { RetryPolicy policy = mock(RetryUpToMaximumCountWithFixedSleep.class); int maxRetries = 8; RetryPolicy realPolicy = retryUpToMaximumCountWithFixedSleep(maxRetries, 1, TimeUnit.NANOSECONDS); setupMockPolicy(policy, realPolicy); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, policy); unreliable.alwaysSucceeds(); unreliable.failsOnceThenSucceeds(); try { unreliable.failsTenTimesThenSucceeds(); fail("Should fail"); } catch (UnreliableException e) { verify(policy, times(maxRetries + 2)).shouldRetry(any(Exception.class), anyInt(), anyInt(), anyBoolean()); assertEquals(RetryDecision.FAIL, caughtRetryAction.action); assertEquals(RetryUpToMaximumCountWithFixedSleep.constructReasonString( maxRetries), caughtRetryAction.reason); } catch (Exception e) { fail("Other exception other than UnreliableException should also get " + "failed."); } }
@Test public void testRetryUpToMaximumTimeWithFixedSleep() throws Exception { RetryPolicy policy = mock(RetryUpToMaximumTimeWithFixedSleep.class); long maxTime = 80L; RetryPolicy realPolicy = retryUpToMaximumTimeWithFixedSleep(maxTime, 10, TimeUnit.NANOSECONDS); setupMockPolicy(policy, realPolicy); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, policy); unreliable.alwaysSucceeds(); unreliable.failsOnceThenSucceeds(); try { unreliable.failsTenTimesThenSucceeds(); fail("Should fail"); } catch (UnreliableException e) { verify(policy, times((int)(maxTime/10) + 2)).shouldRetry(any(Exception.class), anyInt(), anyInt(), anyBoolean()); assertEquals(RetryDecision.FAIL, caughtRetryAction.action); assertEquals(RetryUpToMaximumTimeWithFixedSleep.constructReasonString( maxTime, TimeUnit.NANOSECONDS), caughtRetryAction.reason); } catch (Exception e) { fail("Other exception other than UnreliableException should also get " + "failed."); } }
@Test public void testRetryUpToMaximumCountWithProportionalSleep() throws UnreliableException { UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, retryUpToMaximumCountWithProportionalSleep(8, 1, TimeUnit.NANOSECONDS)); unreliable.alwaysSucceeds(); unreliable.failsOnceThenSucceeds(); try { unreliable.failsTenTimesThenSucceeds(); fail("Should fail"); } catch (UnreliableException e) { } }
@Test public void testExponentialRetry() throws UnreliableException { UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, exponentialBackoffRetry(5, 1L, TimeUnit.NANOSECONDS)); unreliable.alwaysSucceeds(); unreliable.failsOnceThenSucceeds(); try { unreliable.failsTenTimesThenSucceeds(); fail("Should fail"); } catch (UnreliableException e) { } }
@Test public void testRetryByException() throws UnreliableException { Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap = Collections.<Class<? extends Exception>, RetryPolicy>singletonMap(FatalException.class, TRY_ONCE_THEN_FAIL); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, retryByException(RETRY_FOREVER, exceptionToPolicyMap)); unreliable.failsOnceThenSucceeds(); try { unreliable.alwaysFailsWithFatalException(); fail("Should fail"); } catch (FatalException e) { } }
@Test public void testRetryByRemoteException() { Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap = Collections.<Class<? extends Exception>, RetryPolicy>singletonMap(FatalException.class, TRY_ONCE_THEN_FAIL); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, retryByRemoteException(RETRY_FOREVER, exceptionToPolicyMap)); try { unreliable.alwaysFailsWithRemoteFatalException(); fail("Should fail"); } catch (RemoteException e) { } }
@Test public void testRetryOtherThanRemoteException() throws Throwable { Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap = Collections.<Class<? extends Exception>, RetryPolicy>singletonMap( IOException.class, RETRY_FOREVER); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, retryOtherThanRemoteException(TRY_ONCE_THEN_FAIL, exceptionToPolicyMap)); unreliable.failsOnceWithIOException(); try { unreliable.failsOnceWithRemoteException(); fail("Should fail"); } catch (RemoteException e) { } }
@Test public void testRetryInterruptible() throws Throwable { final UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(UnreliableInterface.class, unreliableImpl, retryUpToMaximumTimeWithFixedSleep(10, 10, TimeUnit.SECONDS)); final CountDownLatch latch = new CountDownLatch(1); final AtomicReference<Thread> futureThread = new AtomicReference<Thread>(); ExecutorService exec = Executors.newSingleThreadExecutor(); Future<Throwable> future = exec.submit(new Callable<Throwable>(){ @Override public Throwable call() throws Exception { futureThread.set(Thread.currentThread()); latch.countDown(); try { unreliable.alwaysFailsWithFatalException(); } catch (UndeclaredThrowableException ute) { return ute.getCause(); } return null; } }); latch.await(); Thread.sleep(1000); assertTrue(futureThread.get().isAlive()); futureThread.get().interrupt(); Throwable e = future.get(1, TimeUnit.SECONDS); assertNotNull(e); assertEquals(InterruptedIOException.class, e.getClass()); assertEquals("Retry interrupted", e.getMessage()); assertEquals(InterruptedException.class, e.getCause().getClass()); assertEquals("sleep interrupted", e.getCause().getMessage()); }
@Test public void testNoRetryOnSaslError() throws Exception { RetryPolicy policy = mock(RetryPolicy.class); RetryPolicy realPolicy = RetryPolicies.failoverOnNetworkException(5); setupMockPolicy(policy, realPolicy); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create( UnreliableInterface.class, unreliableImpl, policy); try { unreliable.failsWithSASLExceptionTenTimes(); fail("Should fail"); } catch (SaslException e) { verify(policy, times(1)).shouldRetry(any(Exception.class), anyInt(), anyInt(), anyBoolean()); assertEquals(RetryDecision.FAIL, caughtRetryAction.action); } }
@Test public void testNoRetryOnAccessControlException() throws Exception { RetryPolicy policy = mock(RetryPolicy.class); RetryPolicy realPolicy = RetryPolicies.failoverOnNetworkException(5); setupMockPolicy(policy, realPolicy); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create( UnreliableInterface.class, unreliableImpl, policy); try { unreliable.failsWithAccessControlExceptionEightTimes(); fail("Should fail"); } catch (AccessControlException e) { verify(policy, times(1)).shouldRetry(any(Exception.class), anyInt(), anyInt(), anyBoolean()); assertEquals(RetryDecision.FAIL, caughtRetryAction.action); } }
@Test public void testWrappedAccessControlException() throws Exception { RetryPolicy policy = mock(RetryPolicy.class); RetryPolicy realPolicy = RetryPolicies.failoverOnNetworkException(5); setupMockPolicy(policy, realPolicy); UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create( UnreliableInterface.class, unreliableImpl, policy); try { unreliable.failsWithWrappedAccessControlException(); fail("Should fail"); } catch (IOException expected) { verify(policy, times(1)).shouldRetry(any(Exception.class), anyInt(), anyInt(), anyBoolean()); assertEquals(RetryDecision.FAIL, caughtRetryAction.action); } }