protected internal virtual void DefaultTerminateEndEventBehaviour(IExecutionEntity execution, ICommandContext commandContext, IExecutionEntityManager executionEntityManager)
        {
            IExecutionEntity scopeExecutionEntity = executionEntityManager.FindFirstScope(execution);

            SendProcessInstanceCancelledEvent(scopeExecutionEntity, execution.CurrentFlowElement);

            // If the scope is the process instance, we can just terminate it all
            // Special treatment is needed when the terminated activity is a subprocess (embedded/callactivity/..)
            // The subprocess is destroyed, but the execution calling it, continues further on.
            // In case of a multi-instance subprocess, only one instance is terminated, the other instances continue to exist.

            string deleteReason = CreateDeleteReason(execution.CurrentActivityId);

            if (scopeExecutionEntity.ProcessInstanceType && scopeExecutionEntity.SuperExecutionId is null)
            {
                EndAllHistoricActivities(scopeExecutionEntity.Id, deleteReason);
                DeleteExecutionEntities(executionEntityManager, scopeExecutionEntity, deleteReason);
                commandContext.HistoryManager.RecordProcessInstanceEnd(scopeExecutionEntity.Id, deleteReason, execution.CurrentActivityId);
            }
            else if (scopeExecutionEntity.CurrentFlowElement != null && scopeExecutionEntity.CurrentFlowElement is SubProcess)
            { // SubProcess
                SubProcess subProcess = (SubProcess)scopeExecutionEntity.CurrentFlowElement;

                scopeExecutionEntity.DeleteReason = deleteReason;
                if (subProcess.HasMultiInstanceLoopCharacteristics())
                {
                    Context.Agenda.PlanDestroyScopeOperation(scopeExecutionEntity);
                    MultiInstanceActivityBehavior multiInstanceBehavior = (MultiInstanceActivityBehavior)subProcess.Behavior;
                    multiInstanceBehavior.Leave(scopeExecutionEntity);
                }
                else
                {
                    Context.Agenda.PlanDestroyScopeOperation(scopeExecutionEntity);
                    IExecutionEntity outgoingFlowExecution = executionEntityManager.CreateChildExecution(scopeExecutionEntity.Parent);
                    outgoingFlowExecution.CurrentFlowElement = scopeExecutionEntity.CurrentFlowElement;
                    Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(outgoingFlowExecution, true);
                }
            }
            else if (scopeExecutionEntity.ParentId is null && scopeExecutionEntity.SuperExecutionId is object)
            { // CallActivity
                IExecutionEntity callActivityExecution = scopeExecutionEntity.SuperExecution;
                CallActivity     callActivity          = (CallActivity)callActivityExecution.CurrentFlowElement;

                if (callActivity.HasMultiInstanceLoopCharacteristics())
                {
                    MultiInstanceActivityBehavior multiInstanceBehavior = (MultiInstanceActivityBehavior)callActivity.Behavior;
                    multiInstanceBehavior.Leave(callActivityExecution);
                    executionEntityManager.DeleteProcessInstanceExecutionEntity(scopeExecutionEntity.Id, execution.CurrentFlowElement.Id, "terminate end event", false, false);
                }
                else
                {
                    executionEntityManager.DeleteProcessInstanceExecutionEntity(scopeExecutionEntity.Id, execution.CurrentFlowElement.Id, "terminate end event", false, false);
                    IExecutionEntity superExecutionEntity = executionEntityManager.FindById <IExecutionEntity>(scopeExecutionEntity.SuperExecutionId);
                    Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(superExecutionEntity, true);
                }
            }
        }
Ejemplo n.º 2
0
        protected internal virtual void DeleteChildExecutions(IExecutionEntity parentExecution, IExecutionEntity notToDeleteExecution, ICommandContext commandContext)
        {
            // TODO: would be good if this deleteChildExecutions could be removed and the one on the executionEntityManager is used
            // The problem however, is that the 'notToDeleteExecution' is passed here.
            // This could be solved by not reusing an execution, but creating a new

            // Delete all child executions
            IExecutionEntityManager        executionEntityManager = commandContext.ExecutionEntityManager;
            ICollection <IExecutionEntity> childExecutions        = executionEntityManager.FindChildExecutionsByParentExecutionId(parentExecution.Id);

            if (CollectionUtil.IsNotEmpty(childExecutions))
            {
                foreach (IExecutionEntity childExecution in childExecutions)
                {
                    if (childExecution.Id.Equals(notToDeleteExecution.Id) == false)
                    {
                        DeleteChildExecutions(childExecution, notToDeleteExecution, commandContext);
                    }
                }
            }

            string deleteReason = History.DeleteReasonFields.BOUNDARY_EVENT_INTERRUPTING + " (" + notToDeleteExecution.CurrentActivityId + ")";

            if (parentExecution.CurrentFlowElement is CallActivity)
            {
                IExecutionEntity subProcessExecution = executionEntityManager.FindSubProcessInstanceBySuperExecutionId(parentExecution.Id);
                if (subProcessExecution != null)
                {
                    executionEntityManager.DeleteProcessInstanceExecutionEntity(subProcessExecution.Id, subProcessExecution.CurrentActivityId, deleteReason, true, true);
                }
            }

            executionEntityManager.DeleteExecutionAndRelatedData(parentExecution, deleteReason, false);
        }
Ejemplo n.º 3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="processInstanceExecution"></param>
        protected internal virtual void HandleProcessInstanceExecution(IExecutionEntity processInstanceExecution)
        {
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            string processInstanceId = processInstanceExecution.Id;

            // No parent execution == process instance id
            logger.LogDebug($"No parent execution found. Verifying if process instance {processInstanceId} can be stopped.");

            IExecutionEntity            superExecution             = processInstanceExecution.SuperExecution;
            ISubProcessActivityBehavior subProcessActivityBehavior = null;

            // copy variables before destroying the ended sub process instance (call activity)
            if (superExecution != null)
            {
                FlowNode superExecutionElement = (FlowNode)superExecution.CurrentFlowElement;
                subProcessActivityBehavior = (ISubProcessActivityBehavior)superExecutionElement.Behavior;
                try
                {
                    subProcessActivityBehavior.Completing(superExecution, processInstanceExecution);
                }
                //catch (Exception e)
                //{
                //    //logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
                //    throw e;
                //}
                catch (Exception e)
                {
                    logger.LogError($"Error while completing sub process of execution {processInstanceExecution}.Exception Message: {e.Message}");
                    throw new ActivitiException("Error while completing sub process of execution " + processInstanceExecution, e);
                }
            }

            int activeExecutions = GetNumberOfActiveChildExecutionsForProcessInstance(executionEntityManager, processInstanceId, superExecution);

            if (activeExecutions == 0)
            {
                logger.LogDebug($"No active executions found. Ending process instance {processInstanceId} ");

                // note the use of execution here vs processinstance execution for getting the flowelement
                executionEntityManager.DeleteProcessInstanceExecutionEntity(processInstanceId, execution.CurrentFlowElement?.Id, null, false, false);
            }
            else
            {
                logger.LogDebug($"Active executions found. Process instance {processInstanceId} will not be ended.");
            }

            Process process = ProcessDefinitionUtil.GetProcess(processInstanceExecution.ProcessDefinitionId);

            // Execute execution listeners for process end.
            if (CollectionUtil.IsNotEmpty(process.ExecutionListeners))
            {
                ExecuteExecutionListeners(process, processInstanceExecution, BaseExecutionListenerFields.EVENTNAME_END);
            }

            // and trigger execution afterwards if doing a call activity
            if (superExecution != null)
            {
                superExecution.SubProcessInstance = null;
                try
                {
                    subProcessActivityBehavior.Completed(superExecution);
                }
                //catch (Exception e)
                //{
                //    logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
                //    throw e;
                //}
                catch (Exception e)
                {
                    logger.LogError($"Error while completing sub process of execution {processInstanceExecution}. Exception Messgae: {e.Message}.");
                    throw new ActivitiException("Error while completing sub process of execution " + processInstanceExecution, e);
                }
            }
        }
Ejemplo n.º 4
0
        public override void Leave(IExecutionEntity execution, object signalData)
        {
            lock (syncRoot)
            {
                ICommandContext commandContext = Context.CommandContext;
                if (commandContext == null)
                {
                    throw new ActivitiException("lazy loading outside command context");
                }

                completedPolicy.LeaveExection = execution;

                bool zeroNrOfInstances = false;
                if (ResolveNrOfInstances(execution) == 0)
                {
                    // Empty collection, just leave.
                    zeroNrOfInstances = true;
                    RemoveLocalLoopVariable(execution, CollectionElementIndexVariable);
                    base.Leave(execution, signalData); // Plan the default leave
                    execution.IsMultiInstanceRoot = false;
                }

                int loopCounter            = GetLoopVariable(execution, CollectionElementIndexVariable).GetValueOrDefault(0);
                int nrOfInstances          = GetLoopVariable(execution, NUMBER_OF_INSTANCES).GetValueOrDefault(0);
                int nrOfCompletedInstances = GetLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES).GetValueOrDefault(0) + 1;
                int nrOfActiveInstances    = GetLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES).GetValueOrDefault(0) - 1;

                Context.CommandContext.HistoryManager.RecordActivityEnd(execution, null);
                CallActivityEndListeners(execution);

                if (zeroNrOfInstances)
                {
                    return;
                }

                IExecutionEntity miRootExecution = GetMultiInstanceRootExecution(execution);
                if (miRootExecution != null)
                { // will be null in case of empty collection
                    SetLoopVariable(miRootExecution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances);
                    SetLoopVariable(miRootExecution, NUMBER_OF_ACTIVE_INSTANCES, nrOfActiveInstances < 0 ? 0 : nrOfActiveInstances);
                }

                //ExecuteCompensationBoundaryEvents(execution.CurrentFlowElement, execution);

                LogLoopDetails(execution, "instance completed", loopCounter, nrOfCompletedInstances, nrOfActiveInstances, nrOfActiveInstances < 0 ? 0 : nrOfActiveInstances);

                if (execution.Parent != null)
                {
                    execution.Inactivate();
                    LockFirstParentScope(execution);

                    if (CompletionConditionSatisfied(execution.Parent, signalData) || nrOfCompletedInstances >= nrOfInstances)
                    {
                        IExecutionEntity executionToUse;
                        if (nrOfInstances > 0)
                        {
                            executionToUse = execution.Parent;
                        }
                        else
                        {
                            executionToUse = execution;
                        }

                        bool     hasCompensation = false;
                        Activity activity        = (Activity)execution.CurrentFlowElement;
                        if (activity is Transaction)
                        {
                            hasCompensation = true;
                        }
                        else if (activity is SubProcess subProcess)
                        {
                            foreach (FlowElement subElement in subProcess.FlowElements)
                            {
                                if (subElement is Activity subActivity)
                                {
                                    if (CollectionUtil.IsNotEmpty(subActivity.BoundaryEvents))
                                    {
                                        foreach (BoundaryEvent boundaryEvent in subActivity.BoundaryEvents)
                                        {
                                            if (CollectionUtil.IsNotEmpty(boundaryEvent.EventDefinitions) && boundaryEvent.EventDefinitions[0] is CompensateEventDefinition)
                                            {
                                                hasCompensation = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (hasCompensation)
                        {
                            ScopeUtil.CreateCopyOfSubProcessExecutionForCompensation(executionToUse);
                        }

                        if (activity is CallActivity)
                        {
                            IExecutionEntityManager executionEntityManager = Context.CommandContext.ExecutionEntityManager;
                            if (executionToUse != null)
                            {
                                IList <string> callActivityExecutionIds = new List <string>();

                                // Find all execution entities that are at the call activity
                                IList <IExecutionEntity> childExecutions = executionEntityManager.CollectChildren(executionToUse);
                                if (childExecutions != null)
                                {
                                    foreach (IExecutionEntity childExecution in childExecutions)
                                    {
                                        if (activity.Id.Equals(childExecution.CurrentActivityId))
                                        {
                                            callActivityExecutionIds.Add(childExecution.Id);
                                        }
                                    }

                                    // Now all call activity executions have been collected, loop again and check which should be removed
                                    for (int i = childExecutions.Count - 1; i >= 0; i--)
                                    {
                                        IExecutionEntity childExecution = childExecutions[i];
                                        if (!string.IsNullOrWhiteSpace(childExecution.SuperExecutionId) && callActivityExecutionIds.Contains(childExecution.SuperExecutionId))
                                        {
                                            executionEntityManager.DeleteProcessInstanceExecutionEntity(childExecution.Id, activity.Id, "call activity completion condition met", true, false);
                                        }
                                    }
                                }
                            }
                        }

                        DeleteChildExecutions(executionToUse, false, Context.CommandContext);
                        RemoveLocalLoopVariable(executionToUse, CollectionElementIndexVariable);
                        executionToUse.IsScope             = false;
                        executionToUse.IsMultiInstanceRoot = false;
                        Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(executionToUse, true);
                    }
                }
                else
                {
                    RemoveLocalLoopVariable(execution, CollectionElementIndexVariable);
                    execution.IsMultiInstanceRoot = false;
                    base.Leave(execution, signalData);
                }
            }
        }
Ejemplo n.º 5
0
        public static void PropagateError(string errorCode, IExecutionEntity execution)
        {
            IDictionary <string, IList <Event> > eventMap = FindCatchingEventsForProcess(execution.ProcessDefinitionId, errorCode);

            if (eventMap.Count > 0)
            {
                ExecuteCatch(eventMap, execution, errorCode);
            }
            else if (!execution.ProcessInstanceId.Equals(execution.RootProcessInstanceId))
            { // Call activity
                IExecutionEntityManager executionEntityManager   = Context.CommandContext.ExecutionEntityManager;
                IExecutionEntity        processInstanceExecution = executionEntityManager.FindById <IExecutionEntity>(execution.ProcessInstanceId);
                if (processInstanceExecution != null)
                {
                    IExecutionEntity parentExecution = processInstanceExecution.SuperExecution;

                    IList <string> toDeleteProcessInstanceIds = new List <string>
                    {
                        execution.ProcessInstanceId
                    };

                    while (parentExecution != null && eventMap.Count == 0)
                    {
                        eventMap = FindCatchingEventsForProcess(parentExecution.ProcessDefinitionId, errorCode);
                        if (eventMap.Count > 0)
                        {
                            foreach (string processInstanceId in toDeleteProcessInstanceIds)
                            {
                                IExecutionEntity processInstanceEntity = executionEntityManager.FindById <IExecutionEntity>(processInstanceId);

                                // Delete
                                executionEntityManager.DeleteProcessInstanceExecutionEntity(processInstanceEntity.Id, execution.CurrentFlowElement?.Id, "ERROR_EVENT " + errorCode, false, false);

                                // Event
                                ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration;
                                if (!(processEngineConfiguration is null) && Context.ProcessEngineConfiguration.EventDispatcher.Enabled)
                                {
                                    processEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateEntityEvent(ActivitiEventType.PROCESS_COMPLETED_WITH_ERROR_END_EVENT, processInstanceEntity));
                                }
                            }
                            ExecuteCatch(eventMap, parentExecution, errorCode);
                        }
                        else
                        {
                            toDeleteProcessInstanceIds.Add(parentExecution.ProcessInstanceId);
                            IExecutionEntity superExecution = parentExecution.SuperExecution;
                            if (superExecution != null)
                            {
                                parentExecution = superExecution;
                            }
                            else if (!parentExecution.Id.Equals(parentExecution.RootProcessInstanceId))
                            { // stop at the root
                                parentExecution = parentExecution.ProcessInstance;
                            }
                            else
                            {
                                parentExecution = null;
                            }
                        }
                    }
                }
            }

            if (eventMap.Count == 0)
            {
                throw new BpmnError(errorCode, "No catching boundary event found for error with errorCode '" + errorCode + "', neither in same process nor in parent process");
            }
        }