AdvancedDcMetaService implements DcMetaService { @VisibleForTesting protected <T> Command<T> retry3TimesUntilSuccess(Command<T> command) { return factory.createRetryCommand(command); }  @PostConstruct void initService(); @Override DcMeta getDcMeta(String dcName); @Override DcMeta getDcMeta(String dcName, Set<String> allowTypes); AdvancedDcMetaService setScheduled(ScheduledExecutorService scheduled); AdvancedDcMetaService setExecutors(ExecutorService executors); AdvancedDcMetaService setFactory(RetryCommandFactory factory);  }
@Test public void testRetry3TimesUntilSuccess() throws Exception { ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1); service.setScheduled(scheduled).setFactory(new DefaultRetryCommandFactory(3, new RetryDelay(10), scheduled)); Command<String> command = service.retry3TimesUntilSuccess(new AbstractCommand<String>() { private AtomicInteger counter = new AtomicInteger(0); @Override protected void doExecute() throws Exception { int currentCount = counter.getAndIncrement(); logger.info(String.format("Run %d time", currentCount)); if(currentCount > 1) { future().setSuccess("success"); } else { throw new XpipeRuntimeException("test exception"); } } @Override protected void doReset() { } @Override public String getName() { return "test-retry"; } }); AtomicBoolean complete = new AtomicBoolean(false); command.future().addListener(commandFuture -> { Assert.assertEquals("success", commandFuture.getNow()); complete.getAndSet(true); }); command.execute(); waitConditionUntilTimeOut(() -> complete.get()); }