Search in sources :

Example 1 with ProcessContext

use of io.seata.saga.proctrl.ProcessContext in project seata by seata.

the class LoopTaskUtils method putContextToParent.

/**
 * put loop out params to parent context
 *
 * @param context
 */
public static void putContextToParent(ProcessContext context, List<ProcessContext> subContextList, State state) {
    Map<String, Object> contextVariables = (Map<String, Object>) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT);
    if (CollectionUtils.isNotEmpty(subContextList)) {
        StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
        List<Map<String, Object>> subContextVariables = new ArrayList<>();
        for (ProcessContext subProcessContext : subContextList) {
            StateInstance stateInstance = (StateInstance) subProcessContext.getVariable(DomainConstants.VAR_NAME_STATE_INST);
            Map<String, Object> outputVariablesToContext = ParameterUtils.createOutputParams(stateMachineConfig.getExpressionFactoryManager(), (AbstractTaskState) state, stateInstance.getOutputParams());
            subContextVariables.add(outputVariablesToContext);
        }
        contextVariables.put(DomainConstants.LOOP_RESULT, subContextVariables);
    }
}
Also used : ArrayList(java.util.ArrayList) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ProcessContext(io.seata.saga.proctrl.ProcessContext) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Example 2 with ProcessContext

use of io.seata.saga.proctrl.ProcessContext in project seata by seata.

the class ProcessCtrlStateMachineEngine method compensateInternal.

public StateMachineInstance compensateInternal(String stateMachineInstId, Map<String, Object> replaceParams, boolean async, AsyncCallback callback) throws EngineExecutionException {
    StateMachineInstance stateMachineInstance = reloadStateMachineInstance(stateMachineInstId);
    if (stateMachineInstance == null) {
        throw new EngineExecutionException("StateMachineInstance is not exits", FrameworkErrorCode.StateMachineInstanceNotExists);
    }
    if (ExecutionStatus.SU.equals(stateMachineInstance.getCompensationStatus())) {
        return stateMachineInstance;
    }
    if (stateMachineInstance.getCompensationStatus() != null) {
        ExecutionStatus[] denyStatus = new ExecutionStatus[] { ExecutionStatus.SU };
        checkStatus(stateMachineInstance, null, denyStatus, null, stateMachineInstance.getCompensationStatus(), "compensate");
    }
    if (replaceParams != null) {
        stateMachineInstance.getEndParams().putAll(replaceParams);
    }
    ProcessContextBuilder contextBuilder = ProcessContextBuilder.create().withProcessType(ProcessType.STATE_LANG).withOperationName(DomainConstants.OPERATION_NAME_COMPENSATE).withAsyncCallback(callback).withStateMachineInstance(stateMachineInstance).withStateMachineConfig(getStateMachineConfig()).withStateMachineEngine(this);
    contextBuilder.withIsAsyncExecution(async);
    ProcessContext context = contextBuilder.build();
    Map<String, Object> contextVariables = getStateMachineContextVariables(stateMachineInstance);
    if (replaceParams != null) {
        contextVariables.putAll(replaceParams);
    }
    putBusinesskeyToContextariables(stateMachineInstance, contextVariables);
    ConcurrentHashMap<String, Object> concurrentContextVariables = new ConcurrentHashMap<>(contextVariables.size());
    nullSafeCopy(contextVariables, concurrentContextVariables);
    context.setVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT, concurrentContextVariables);
    stateMachineInstance.setContext(concurrentContextVariables);
    CompensationTriggerStateImpl tempCompensationTriggerState = new CompensationTriggerStateImpl();
    tempCompensationTriggerState.setStateMachine(stateMachineInstance.getStateMachine());
    stateMachineInstance.setRunning(true);
    if (LOGGER.isInfoEnabled()) {
        LOGGER.info("Operation [compensate] start.  stateMachineInstance[id:" + stateMachineInstance.getId() + "]");
    }
    if (stateMachineInstance.getStateMachine().isPersist()) {
        stateMachineConfig.getStateLogStore().recordStateMachineRestarted(stateMachineInstance, context);
    }
    try {
        StateInstruction inst = new StateInstruction();
        inst.setTenantId(stateMachineInstance.getTenantId());
        inst.setStateMachineName(stateMachineInstance.getStateMachine().getName());
        inst.setTemporaryState(tempCompensationTriggerState);
        context.setInstruction(inst);
        if (async) {
            stateMachineConfig.getAsyncProcessCtrlEventPublisher().publish(context);
        } else {
            stateMachineConfig.getProcessCtrlEventPublisher().publish(context);
        }
    } catch (EngineExecutionException e) {
        LOGGER.error("Operation [compensate] failed", e);
        throw e;
    }
    return stateMachineInstance;
}
Also used : CompensationTriggerStateImpl(io.seata.saga.statelang.domain.impl.CompensationTriggerStateImpl) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ProcessContext(io.seata.saga.proctrl.ProcessContext) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) ProcessContextBuilder(io.seata.saga.engine.utils.ProcessContextBuilder) ExecutionStatus(io.seata.saga.statelang.domain.ExecutionStatus) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 3 with ProcessContext

use of io.seata.saga.proctrl.ProcessContext in project seata by seata.

the class StateMachineDBTests method simpleChoiceTestStateMachineAsyncConcurrently.

@Test
@Disabled("https://github.com/seata/seata/issues/2414#issuecomment-639546811")
public void simpleChoiceTestStateMachineAsyncConcurrently() throws Exception {
    final CountDownLatch countDownLatch = new CountDownLatch(100);
    final List<Exception> exceptions = new ArrayList<>();
    final AsyncCallback asyncCallback = new AsyncCallback() {

        @Override
        public void onFinished(ProcessContext context, StateMachineInstance stateMachineInstance) {
            countDownLatch.countDown();
        }

        @Override
        public void onError(ProcessContext context, StateMachineInstance stateMachineInstance, Exception exp) {
            countDownLatch.countDown();
            exceptions.add(exp);
        }
    };
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int j = 0; j < 10; j++) {
                    Map<String, Object> paramMap = new HashMap<>();
                    paramMap.put("a", 1);
                    paramMap.put("barThrowException", "false");
                    String stateMachineName = "simpleCompensationStateMachine";
                    try {
                        stateMachineEngine.startAsync(stateMachineName, null, paramMap, asyncCallback);
                    } catch (Exception e) {
                        countDownLatch.countDown();
                        exceptions.add(e);
                    }
                }
            }
        });
        t.start();
    }
    countDownLatch.await(10000, TimeUnit.MILLISECONDS);
    if (exceptions.size() > 0) {
        Assertions.fail(exceptions.get(0));
    }
    long cost = System.currentTimeMillis() - start;
    System.out.println("====== cost :" + cost);
}
Also used : AsyncCallback(io.seata.saga.engine.AsyncCallback) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) TransactionException(io.seata.core.exception.TransactionException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StoreException(io.seata.common.exception.StoreException) ProcessContext(io.seata.saga.proctrl.ProcessContext) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.junit.jupiter.api.Test) Disabled(org.junit.jupiter.api.Disabled)

Example 4 with ProcessContext

use of io.seata.saga.proctrl.ProcessContext in project seata by seata.

the class DirectEventBus method offer.

@Override
public boolean offer(ProcessContext context) throws FrameworkException {
    List<EventConsumer> eventHandlers = getEventConsumers(context.getClass());
    if (CollectionUtils.isEmpty(eventHandlers)) {
        if (LOGGER.isWarnEnabled()) {
            LOGGER.warn("cannot find event handler by class: " + context.getClass());
        }
        return false;
    }
    boolean isFirstEvent = false;
    Stack<ProcessContext> currentStack = (Stack<ProcessContext>) context.getVariable(VAR_NAME_SYNC_EXE_STACK);
    if (currentStack == null) {
        synchronized (context) {
            currentStack = (Stack<ProcessContext>) context.getVariable(VAR_NAME_SYNC_EXE_STACK);
            if (currentStack == null) {
                currentStack = new Stack<>();
                context.setVariable(VAR_NAME_SYNC_EXE_STACK, currentStack);
                isFirstEvent = true;
            }
        }
    }
    currentStack.push(context);
    if (isFirstEvent) {
        try {
            while (currentStack.size() > 0) {
                ProcessContext currentContext = currentStack.pop();
                for (EventConsumer eventHandler : eventHandlers) {
                    eventHandler.process(currentContext);
                }
            }
        } finally {
            context.removeVariable(VAR_NAME_SYNC_EXE_STACK);
        }
    }
    return true;
}
Also used : EventConsumer(io.seata.saga.proctrl.eventing.EventConsumer) ProcessContext(io.seata.saga.proctrl.ProcessContext) Stack(java.util.Stack)

Example 5 with ProcessContext

use of io.seata.saga.proctrl.ProcessContext in project seata by seata.

the class LoopTaskUtils method reloadLoopContext.

/**
 * reload loop counter context while forward
 *
 * @param context
 * @param forwardStateName
 */
public static void reloadLoopContext(ProcessContext context, String forwardStateName) {
    StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
    List<StateInstance> actList = stateMachineInstance.getStateList();
    List<StateInstance> forwardStateList = actList.stream().filter(e -> forwardStateName.equals(EngineUtils.getOriginStateName(e))).collect(Collectors.toList());
    LoopContextHolder loopContextHolder = LoopContextHolder.getCurrent(context, true);
    Collection collection = loopContextHolder.getCollection();
    LinkedList<Integer> list = new LinkedList<>();
    for (int i = 0; i < collection.size(); i++) {
        list.addFirst(i);
    }
    int executedNumber = 0;
    LinkedList<Integer> failEndList = new LinkedList<>();
    for (StateInstance stateInstance : forwardStateList) {
        if (!stateInstance.isIgnoreStatus()) {
            if (ExecutionStatus.SU.equals(stateInstance.getStatus())) {
                executedNumber += 1;
            } else {
                stateInstance.setIgnoreStatus(true);
                failEndList.addFirst(reloadLoopCounter(stateInstance.getName()));
            }
            list.remove(Integer.valueOf(reloadLoopCounter(stateInstance.getName())));
        }
    }
    loopContextHolder.getLoopCounterStack().addAll(list);
    loopContextHolder.getForwardCounterStack().addAll(failEndList);
    loopContextHolder.getNrOfInstances().set(collection.size());
    loopContextHolder.getNrOfCompletedInstances().set(executedNumber);
}
Also used : NumberUtils(io.seata.common.util.NumberUtils) ProcessContextImpl(io.seata.saga.proctrl.impl.ProcessContextImpl) LoggerFactory(org.slf4j.LoggerFactory) DomainConstants(io.seata.saga.statelang.domain.DomainConstants) ArrayList(java.util.ArrayList) ExpressionEvaluator(io.seata.saga.engine.evaluation.expression.ExpressionEvaluator) Map(java.util.Map) EvaluatorFactoryManager(io.seata.saga.engine.evaluation.EvaluatorFactoryManager) ExecutionStatus(io.seata.saga.statelang.domain.ExecutionStatus) LinkedList(java.util.LinkedList) ForwardInvalidException(io.seata.saga.engine.exception.ForwardInvalidException) ProcessContext(io.seata.saga.proctrl.ProcessContext) EmptyStackException(java.util.EmptyStackException) Logger(org.slf4j.Logger) CollectionUtils(io.seata.common.util.CollectionUtils) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) StateInstance(io.seata.saga.statelang.domain.StateInstance) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) StateMachine(io.seata.saga.statelang.domain.StateMachine) Collectors(java.util.stream.Collectors) FrameworkErrorCode(io.seata.common.exception.FrameworkErrorCode) State(io.seata.saga.statelang.domain.State) List(java.util.List) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) Loop(io.seata.saga.statelang.domain.TaskState.Loop) StringUtils(io.seata.common.util.StringUtils) AbstractTaskState(io.seata.saga.statelang.domain.impl.AbstractTaskState) Collection(java.util.Collection) LinkedList(java.util.LinkedList) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) StateInstance(io.seata.saga.statelang.domain.StateInstance)

Aggregations

ProcessContext (io.seata.saga.proctrl.ProcessContext)8 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)6 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)5 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)5 Loop (io.seata.saga.statelang.domain.TaskState.Loop)4 ArrayList (java.util.ArrayList)4 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)4 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)3 ProcessContextBuilder (io.seata.saga.engine.utils.ProcessContextBuilder)3 ExecutionStatus (io.seata.saga.statelang.domain.ExecutionStatus)3 StateInstance (io.seata.saga.statelang.domain.StateInstance)3 Map (java.util.Map)3 ForwardInvalidException (io.seata.saga.engine.exception.ForwardInvalidException)2 ProcessContextImpl (io.seata.saga.proctrl.impl.ProcessContextImpl)2 State (io.seata.saga.statelang.domain.State)2 AbstractTaskState (io.seata.saga.statelang.domain.impl.AbstractTaskState)2 LoopStartStateImpl (io.seata.saga.statelang.domain.impl.LoopStartStateImpl)2 FrameworkErrorCode (io.seata.common.exception.FrameworkErrorCode)1 StoreException (io.seata.common.exception.StoreException)1 CollectionUtils (io.seata.common.util.CollectionUtils)1