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();
}
}
}