protected Object doInvoke()

in saga/seata-saga-spring/src/main/java/org/apache/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java [94:171]


    protected Object doInvoke(ServiceTaskStateImpl state, Object[] input) throws Throwable {

        Object bean = applicationContext.getBean(state.getServiceName());

        Method method = state.getMethod();
        if (method == null) {
            synchronized (state) {
                method = state.getMethod();
                if (method == null) {
                    method = findMethod(bean.getClass(), state.getServiceMethod(), state.getParameterTypes());
                    if (method != null) {
                        state.setMethod(method);
                    }
                }
            }
        }

        if (method == null) {
            throw new EngineExecutionException(
                    "No such method[" + state.getServiceMethod() + "] on BeanClass[" + bean.getClass() + "]",
                    FrameworkErrorCode.NoSuchMethod);

        }

        Object[] args = new Object[method.getParameterCount()];
        try {
            Class[] paramTypes = method.getParameterTypes();
            if (input != null && input.length > 0) {
                int len = input.length < paramTypes.length ? input.length : paramTypes.length;
                for (int i = 0; i < len; i++) {
                    args[i] = toJavaObject(input[i], paramTypes[i]);
                }
            }
        } catch (Exception e) {
            throw new EngineExecutionException(e,
                    "Input to java object error, Method[" + state.getServiceMethod() + "] on BeanClass[" + bean.getClass()
                            + "]", FrameworkErrorCode.InvalidParameter);
        }

        if (!Modifier.isPublic(method.getModifiers())) {
            throw new EngineExecutionException("Method[" + method.getName() + "] must be public",
                    FrameworkErrorCode.MethodNotPublic);
        }

        Map<Retry, AtomicInteger> retryCountMap = new HashMap<>();
        while (true) {
            try {
                return invokeMethod(bean, method, args);
            } catch (Throwable e) {
                Retry matchedRetryConfig = matchRetryConfig(state.getRetry(), e);
                if (matchedRetryConfig == null) {
                    throw e;
                }

                AtomicInteger retryCount = CollectionUtils.computeIfAbsent(retryCountMap, matchedRetryConfig,
                    key -> new AtomicInteger(0));
                if (retryCount.intValue() >= matchedRetryConfig.getMaxAttempts()) {
                    throw e;
                }

                double intervalSeconds = matchedRetryConfig.getIntervalSeconds();
                double backoffRate = matchedRetryConfig.getBackoffRate();
                long currentInterval = (long) (retryCount.intValue() > 0 ?
                        (intervalSeconds * backoffRate * retryCount.intValue() * 1000) : (intervalSeconds * 1000));

                if (LOGGER.isWarnEnabled()) {
                    LOGGER.warn("Invoke Service[" + state.getServiceName() + "." + state.getServiceMethod() + "] failed, will retry after "
                            + currentInterval + " millis, current retry count: " + retryCount.intValue(), e);
                }
                try {
                    Thread.sleep(currentInterval);
                } catch (InterruptedException e1) {
                    LOGGER.warn("Retry interval sleep error", e1);
                }
                retryCount.incrementAndGet();
            }
        }
    }