@Override
    protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
            throws RpcException {
        RetryContext.INSTANCE.markRetry(retry);
        checkInvokers(invokers, invocation);
        final List<io.github.resilience4j.retry.Retry> handlers = retryHandler
                .getHandlers(convertToApacheDubboEntity(invocation, invokers.get(0)));
        final List<Invoker<T>> selected = new ArrayList<>();
        DecorateCheckedSupplier<Result> dcs = Decorators.ofCheckedSupplier(buildFunc(invocation, invokers,
                loadbalance, selected));
        io.github.resilience4j.retry.Retry retryRule = null;
        if (!handlers.isEmpty()) {
            // only one policy is supported for retry
            retryRule = handlers.get(0);
            dcs.withRetry(retryRule);
        }
        try {
            return dcs.get();
        } catch (RpcException ex) {
            log(retryRule, invocation);
            throw ex;
        } catch (Throwable ex) {
            log(retryRule, invocation);
            throw formatEx(ex);
        } finally {
            RetryContext.INSTANCE.remove();
            FlowControlContext.INSTANCE.clear();
            selected.clear();
        }
    }
@Test
    public void doInvoke() {
        final Directory<Result> directory = Mockito.mock(Directory.class);
        Mockito.when(directory.getUrl()).thenReturn(new URL("dubbo", "localhost", 8080));
        final ApacheDubboClusterInvoker<Result> clusterInvoker = new ApacheDubboClusterInvoker<>(directory);
        final RoundRobinLoadBalance roundRobinLoadBalance = new RoundRobinLoadBalance();
        final Invocation invocation = Mockito.mock(Invocation.class);
        String interfaceName = this.getClass().getName();
        String version = "1.0.0";
        Mockito.when(invocation.getMethodName()).thenReturn("test");
        Mockito.when(invocation.getAttachment(ConvertUtils.DUBBO_ATTACHMENT_VERSION)).thenReturn(version);
        Mockito.when(invocation.getArguments()).thenReturn(new Object[]{"test"});
        final Invoker invoker = Mockito.mock(Invoker.class);
        Mockito.when(invoker.getInterface()).thenReturn(this.getClass());
        final URL url = Mockito.mock(URL.class);
        Mockito.when(url.getParameter(CommonConst.GENERIC_INTERFACE_KEY, interfaceName)).thenReturn(interfaceName);
        Mockito.when(url.getParameter(CommonConst.URL_VERSION_KEY, version)).thenReturn(version);
        Mockito.when(url.getParameter(CommonConst.DUBBO_REMOTE_APPLICATION)).thenReturn("application");
        Mockito.when(invoker.getUrl()).thenReturn(url);
        Mockito.when(invocation.getInvoker()).thenReturn(invoker);
        Mockito.when(directory.getUrl()).thenReturn(url);
        final AsyncRpcResult asyncRpcResult = AsyncRpcResult.newDefaultAsyncResult(new Object(), invocation);
        Mockito.when(invoker.invoke(invocation)).thenReturn(asyncRpcResult);
        final Result result = clusterInvoker.doInvoke(invocation, Arrays.asList(invoker), roundRobinLoadBalance);
        Assert.assertEquals(result, asyncRpcResult);
        // test throw exception
        Mockito.when(invoker.invoke(invocation)).thenThrow(new RpcException("test error"));
        boolean isEx = false;
        try {
            clusterInvoker.doInvoke(invocation, Arrays.asList(invoker), roundRobinLoadBalance);
        } catch (RpcException ex) {
            isEx = true;
        }
        Assert.assertTrue(isEx);
    }