### Question:
ForwardRecovery implements RecoveryPolicy { @Override public SagaResponse apply(SagaTask task, SagaRequest request, SagaResponse parentResponse) { try { for(int i = 0; isRetryable(i, request.transaction()); i++) { try { return request.transaction().send(request.serviceName(), parentResponse); } catch (Exception e) { log.error("Applying {} policy due to failure in transaction {} of service {}", description(), request.transaction(), request.serviceName(), e ); Thread.sleep(request.failRetryDelayMilliseconds()); } } } catch (InterruptedException ignored) { log.warn("Applying {} interrupted in transaction {} of service {}", description(), request.transaction(), request.serviceName(), ignored); throw new TransactionFailedException(ignored); } throw new TransactionAbortedException( String.format( "Too many failures in transaction %s of service %s, abort the transaction!", request.transaction(), request.serviceName())); }  @Override SagaResponse apply(SagaTask task, SagaRequest request, SagaResponse parentResponse); @Override String description();  }### Answer:
@Test public void blowsUpWhenTaskIsNotCommittedWithFailRetryDelaySeconds() throws Exception { doThrow(Exception.class).when(transaction).send(serviceName, parentResponse); Thread t = new Thread(new Runnable() { @Override public void run() { forwardRecovery.apply(sagaTask, sagaRequest, parentResponse); } }); t.start(); Thread.sleep(400); t.interrupt(); verify(transaction, times(2)).send(serviceName, parentResponse); }
@Test public void retriesTransportForSpecifiedTimes() { doThrow(Exception.class).when(transaction).send(serviceName, parentResponse); try { forwardRecovery.apply(sagaTask, sagaRequest, parentResponse); expectFailing(TransactionFailedException.class); } catch (TransactionAbortedException e) { assertThat(e.getMessage(), is("Too many failures in transaction aaa of service aaa, abort the transaction!")); } verify(transaction, times(4)).send(serviceName, parentResponse); }