Search in sources :

Example 1 with ProcessContextImpl

use of io.seata.saga.proctrl.impl.ProcessContextImpl in project seata by seata.

the class LoopTaskUtils method createLoopEventContext.

/**
 * create context for async publish
 *
 * @param context
 * @param loopCounter acquire new counter if is -1, else means a specific loop-counter
 * @return
 */
public static ProcessContext createLoopEventContext(ProcessContext context, int loopCounter) {
    ProcessContextImpl copyContext = new ProcessContextImpl();
    copyContext.setParent(context);
    copyContext.setVariableLocally(DomainConstants.LOOP_COUNTER, loopCounter >= 0 ? loopCounter : acquireNextLoopCounter(context));
    copyContext.setInstruction(copyInstruction(context.getInstruction(StateInstruction.class)));
    return copyContext;
}
Also used : ProcessContextImpl(io.seata.saga.proctrl.impl.ProcessContextImpl)

Example 2 with ProcessContextImpl

use of io.seata.saga.proctrl.impl.ProcessContextImpl in project seata by seata.

the class ProcessControllerTests method testSimpleProcessCtrl.

@Test
public void testSimpleProcessCtrl() {
    try {
        ProcessCtrlEventPublisher processCtrlEventPublisher = buildEventPublisher();
        ProcessContext context = new ProcessContextImpl();
        MockInstruction instruction = new MockInstruction();
        instruction.setTestString("one");
        context.setInstruction(instruction);
        context.setVariable("TEST", "test");
        processCtrlEventPublisher.publish(context);
    } catch (Exception e) {
        Assertions.fail(e);
    }
}
Also used : ProcessContextImpl(io.seata.saga.proctrl.impl.ProcessContextImpl) MockInstruction(io.seata.saga.proctrl.mock.MockInstruction) ProcessCtrlEventPublisher(io.seata.saga.proctrl.eventing.impl.ProcessCtrlEventPublisher) Test(org.junit.jupiter.api.Test)

Example 3 with ProcessContextImpl

use of io.seata.saga.proctrl.impl.ProcessContextImpl in project seata by seata.

the class ProcessControllerTests method testSimpleProcessCtrlAsync.

@Test
public void testSimpleProcessCtrlAsync() {
    try {
        ProcessCtrlEventPublisher processCtrlEventPublisher = buildAsyncEventPublisher();
        ProcessContext context = new ProcessContextImpl();
        MockInstruction instruction = new MockInstruction();
        instruction.setTestString("one");
        context.setInstruction(instruction);
        context.setVariable("TEST", "test");
        processCtrlEventPublisher.publish(context);
    } catch (Exception e) {
        Assertions.fail(e);
    }
}
Also used : ProcessContextImpl(io.seata.saga.proctrl.impl.ProcessContextImpl) MockInstruction(io.seata.saga.proctrl.mock.MockInstruction) ProcessCtrlEventPublisher(io.seata.saga.proctrl.eventing.impl.ProcessCtrlEventPublisher) Test(org.junit.jupiter.api.Test)

Example 4 with ProcessContextImpl

use of io.seata.saga.proctrl.impl.ProcessContextImpl in project seata by seata.

the class LoopStartStateHandler method process.

@Override
public void process(ProcessContext context) throws EngineExecutionException {
    StateInstruction instruction = context.getInstruction(StateInstruction.class);
    StateMachineInstance stateMachineInstance = (StateMachineInstance) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_INST);
    StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
    instruction.setTemporaryState(null);
    Loop loop = LoopTaskUtils.getLoopConfig(context, instruction.getState(context));
    LoopContextHolder loopContextHolder = LoopContextHolder.getCurrent(context, true);
    Semaphore semaphore = null;
    int maxInstances = 0;
    List<ProcessContext> loopContextList = new ArrayList<>();
    if (null != loop) {
        if (!stateMachineConfig.isEnableAsync() || null == stateMachineConfig.getAsyncProcessCtrlEventPublisher()) {
            throw new EngineExecutionException("Asynchronous start is disabled. Loop execution will run asynchronous, please set " + "StateMachineConfig.enableAsync=true first.", FrameworkErrorCode.AsynchronousStartDisabled);
        }
        int totalInstances;
        if (DomainConstants.OPERATION_NAME_FORWARD.equals(context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME))) {
            LoopTaskUtils.reloadLoopContext(context, instruction.getState(context).getName());
            totalInstances = loopContextHolder.getNrOfInstances().get() - loopContextHolder.getNrOfCompletedInstances().get();
        } else {
            LoopTaskUtils.createLoopCounterContext(context);
            totalInstances = loopContextHolder.getNrOfInstances().get();
        }
        maxInstances = Math.min(loop.getParallel(), totalInstances);
        semaphore = new Semaphore(maxInstances);
        context.setVariable(DomainConstants.LOOP_SEMAPHORE, semaphore);
        context.setVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE, true);
        // publish loop tasks
        for (int i = 0; i < totalInstances; i++) {
            try {
                semaphore.acquire();
                ProcessContextImpl tempContext;
                // fail end inst should be forward without completion condition check
                if (!loopContextHolder.getForwardCounterStack().isEmpty()) {
                    int failEndLoopCounter = loopContextHolder.getForwardCounterStack().pop();
                    tempContext = (ProcessContextImpl) LoopTaskUtils.createLoopEventContext(context, failEndLoopCounter);
                } else if (loopContextHolder.isFailEnd() || LoopTaskUtils.isCompletionConditionSatisfied(context)) {
                    semaphore.release();
                    break;
                } else {
                    tempContext = (ProcessContextImpl) LoopTaskUtils.createLoopEventContext(context, -1);
                }
                if (DomainConstants.OPERATION_NAME_FORWARD.equals(context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME))) {
                    ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_IS_FOR_SUB_STATMACHINE_FORWARD, LoopTaskUtils.isForSubStateMachineForward(tempContext));
                }
                stateMachineConfig.getAsyncProcessCtrlEventPublisher().publish(tempContext);
                loopContextHolder.getNrOfActiveInstances().incrementAndGet();
                loopContextList.add(tempContext);
            } catch (InterruptedException e) {
                LOGGER.error("try execute loop task for State: [{}] is interrupted, message: [{}]", instruction.getStateName(), e.getMessage());
                throw new EngineExecutionException(e);
            }
        }
    } else {
        LOGGER.warn("Loop config of State [{}] is illegal, will execute as normal", instruction.getStateName());
        instruction.setTemporaryState(instruction.getState(context));
    }
    try {
        if (null != semaphore) {
            boolean isFinished = false;
            while (!isFinished) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("wait {}ms for loop state [{}] finish", AWAIT_TIMEOUT, instruction.getStateName());
                }
                isFinished = semaphore.tryAcquire(maxInstances, AWAIT_TIMEOUT, TimeUnit.MILLISECONDS);
            }
            if (loopContextList.size() > 0) {
                LoopTaskUtils.putContextToParent(context, loopContextList, instruction.getState(context));
            }
        }
    } catch (InterruptedException e) {
        LOGGER.error("State: [{}] wait loop execution complete is interrupted, message: [{}]", instruction.getStateName(), e.getMessage());
        throw new EngineExecutionException(e);
    } finally {
        context.removeVariable(DomainConstants.LOOP_SEMAPHORE);
        context.removeVariable(DomainConstants.VAR_NAME_IS_LOOP_STATE);
        LoopContextHolder.clearCurrent(context);
    }
    if (loopContextHolder.isFailEnd()) {
        String currentExceptionRoute = LoopTaskUtils.decideCurrentExceptionRoute(loopContextList, stateMachineInstance.getStateMachine());
        if (StringUtils.isNotBlank(currentExceptionRoute)) {
            ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION_ROUTE, currentExceptionRoute);
        } else {
            for (ProcessContext processContext : loopContextList) {
                if (processContext.hasVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION)) {
                    Exception exception = (Exception) processContext.getVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION);
                    EngineUtils.failStateMachine(context, exception);
                    break;
                }
            }
        }
    }
}
Also used : Loop(io.seata.saga.statelang.domain.TaskState.Loop) ProcessContextImpl(io.seata.saga.proctrl.impl.ProcessContextImpl) StateInstruction(io.seata.saga.engine.pcext.StateInstruction) ArrayList(java.util.ArrayList) HierarchicalProcessContext(io.seata.saga.proctrl.HierarchicalProcessContext) Semaphore(java.util.concurrent.Semaphore) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) HierarchicalProcessContext(io.seata.saga.proctrl.HierarchicalProcessContext) ProcessContext(io.seata.saga.proctrl.ProcessContext) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) StateMachineInstance(io.seata.saga.statelang.domain.StateMachineInstance) LoopContextHolder(io.seata.saga.engine.pcext.utils.LoopContextHolder) StateMachineConfig(io.seata.saga.engine.StateMachineConfig)

Aggregations

ProcessContextImpl (io.seata.saga.proctrl.impl.ProcessContextImpl)4 ProcessCtrlEventPublisher (io.seata.saga.proctrl.eventing.impl.ProcessCtrlEventPublisher)2 MockInstruction (io.seata.saga.proctrl.mock.MockInstruction)2 Test (org.junit.jupiter.api.Test)2 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)1 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)1 StateInstruction (io.seata.saga.engine.pcext.StateInstruction)1 LoopContextHolder (io.seata.saga.engine.pcext.utils.LoopContextHolder)1 HierarchicalProcessContext (io.seata.saga.proctrl.HierarchicalProcessContext)1 ProcessContext (io.seata.saga.proctrl.ProcessContext)1 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)1 Loop (io.seata.saga.statelang.domain.TaskState.Loop)1 ArrayList (java.util.ArrayList)1 Semaphore (java.util.concurrent.Semaphore)1