Search in sources :

Example 6 with ServiceTaskStateImpl

use of io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl in project seata by seata.

the class SpringBeanServiceInvoker method doInvoke.

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();
        }
    }
}
Also used : ExceptionUtils(io.seata.saga.engine.utils.ExceptionUtils) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ArrayList(java.util.ArrayList) BigDecimal(java.math.BigDecimal) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) JsonParser(io.seata.saga.statelang.parser.JsonParser) BigInteger(java.math.BigInteger) ServiceInvoker(io.seata.saga.engine.invoker.ServiceInvoker) Method(java.lang.reflect.Method) ServiceTaskStateHandler(io.seata.saga.engine.pcext.handlers.ServiceTaskStateHandler) JsonParserFactory(io.seata.saga.statelang.parser.JsonParserFactory) Logger(org.slf4j.Logger) Retry(io.seata.saga.statelang.domain.TaskState.Retry) CollectionUtils(io.seata.common.util.CollectionUtils) ServiceTaskState(io.seata.saga.statelang.domain.ServiceTaskState) FrameworkErrorCode(io.seata.common.exception.FrameworkErrorCode) ApplicationContext(org.springframework.context.ApplicationContext) InvocationTargetException(java.lang.reflect.InvocationTargetException) List(java.util.List) ServiceTaskStateImpl(io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl) Modifier(java.lang.reflect.Modifier) ApplicationContextAware(org.springframework.context.ApplicationContextAware) BeanUtils(org.springframework.beans.BeanUtils) HashMap(java.util.HashMap) Method(java.lang.reflect.Method) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) InvocationTargetException(java.lang.reflect.InvocationTargetException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Retry(io.seata.saga.statelang.domain.TaskState.Retry)

Example 7 with ServiceTaskStateImpl

use of io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl in project seata by seata.

the class ProcessCtrlStateMachineEngine method replayContextVariables.

protected Map<String, Object> replayContextVariables(StateMachineInstance stateMachineInstance) {
    Map<String, Object> contextVariables = new HashMap<>();
    if (stateMachineInstance.getStartParams() == null) {
        contextVariables.putAll(stateMachineInstance.getStartParams());
    }
    List<StateInstance> stateInstanceList = stateMachineInstance.getStateList();
    if (CollectionUtils.isEmpty(stateInstanceList)) {
        return contextVariables;
    }
    for (StateInstance stateInstance : stateInstanceList) {
        Object serviceOutputParams = stateInstance.getOutputParams();
        if (serviceOutputParams != null) {
            ServiceTaskStateImpl state = (ServiceTaskStateImpl) stateMachineInstance.getStateMachine().getState(EngineUtils.getOriginStateName(stateInstance));
            if (state == null) {
                throw new EngineExecutionException("Cannot find State by state name [" + stateInstance.getName() + "], may be this is a bug", FrameworkErrorCode.ObjectNotExists);
            }
            if (CollectionUtils.isNotEmpty(state.getOutput())) {
                try {
                    Map<String, Object> outputVariablesToContext = ParameterUtils.createOutputParams(stateMachineConfig.getExpressionFactoryManager(), state, serviceOutputParams);
                    if (CollectionUtils.isNotEmpty(outputVariablesToContext)) {
                        contextVariables.putAll(outputVariablesToContext);
                    }
                    if (StringUtils.hasLength(stateInstance.getBusinessKey())) {
                        contextVariables.put(state.getName() + DomainConstants.VAR_NAME_BUSINESSKEY, stateInstance.getBusinessKey());
                    }
                } catch (Exception e) {
                    throw new EngineExecutionException(e, "Context variables replay faied", FrameworkErrorCode.ContextVariableReplayFailed);
                }
            }
        }
    }
    return contextVariables;
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) StateInstance(io.seata.saga.statelang.domain.StateInstance) ServiceTaskStateImpl(io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl)

Aggregations

ServiceTaskStateImpl (io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl)7 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)5 StateInstance (io.seata.saga.statelang.domain.StateInstance)5 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)4 Map (java.util.Map)4 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)3 ServiceInvoker (io.seata.saga.engine.invoker.ServiceInvoker)2 HierarchicalProcessContext (io.seata.saga.proctrl.HierarchicalProcessContext)2 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)2 ArrayList (java.util.ArrayList)2 Date (java.util.Date)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 ApplicationContextAware (org.springframework.context.ApplicationContextAware)2 FrameworkErrorCode (io.seata.common.exception.FrameworkErrorCode)1 CollectionUtils (io.seata.common.util.CollectionUtils)1 StateMachineEngine (io.seata.saga.engine.StateMachineEngine)1 ForwardInvalidException (io.seata.saga.engine.exception.ForwardInvalidException)1 DefaultStateMachineConfig (io.seata.saga.engine.impl.DefaultStateMachineConfig)1