public override void Trigger(IExecutionEntity execution, string triggerName, object triggerData, bool throwError = true) { BoundaryEvent boundaryEvent = (BoundaryEvent)execution.CurrentFlowElement; ICommandContext commandContext = Context.CommandContext; IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager; IExecutionEntity subProcessExecution = null; // TODO: this can be optimized. A full search in the all executions shouldn't be needed IList <IExecutionEntity> processInstanceExecutions = executionEntityManager.FindChildExecutionsByProcessInstanceId(execution.ProcessInstanceId); foreach (IExecutionEntity childExecution in processInstanceExecutions) { if (childExecution.CurrentFlowElement != null && childExecution.CurrentFlowElement.Id.Equals(boundaryEvent.AttachedToRefId)) { subProcessExecution = childExecution; break; } } if (subProcessExecution == null) { throw new ActivitiException("No execution found for sub process of boundary cancel event " + boundaryEvent.Id); } IEventSubscriptionEntityManager eventSubscriptionEntityManager = commandContext.EventSubscriptionEntityManager; IList <ICompensateEventSubscriptionEntity> eventSubscriptions = eventSubscriptionEntityManager.FindCompensateEventSubscriptionsByExecutionId(subProcessExecution.ParentId); if (eventSubscriptions.Count == 0) { Leave(execution); } else { Leave(execution); string deleteReason = History.DeleteReasonFields.BOUNDARY_EVENT_INTERRUPTING + "(" + boundaryEvent.Id + ")"; // cancel boundary is always sync ScopeUtil.ThrowCompensationEvent(eventSubscriptions, execution, false); executionEntityManager.DeleteExecutionAndRelatedData(subProcessExecution, deleteReason, false); if (subProcessExecution.CurrentFlowElement is Activity activity) { if (activity.LoopCharacteristics != null) { IExecutionEntity miExecution = subProcessExecution.Parent; IList <IExecutionEntity> miChildExecutions = executionEntityManager.FindChildExecutionsByParentExecutionId(miExecution.Id); foreach (IExecutionEntity miChildExecution in miChildExecutions) { if (subProcessExecution.Id.Equals(miChildExecution.Id) == false && activity.Id.Equals(miChildExecution.CurrentActivityId)) { executionEntityManager.DeleteExecutionAndRelatedData(miChildExecution, deleteReason, false); } } } } } }
/// <summary> /// /// </summary> /// <param name="executionEntityManager"></param> /// <param name="processInstanceId"></param> /// <returns></returns> protected internal virtual int GetNumberOfActiveChildExecutionsForProcessInstance(IExecutionEntityManager executionEntityManager, string processInstanceId) { ICollection <IExecutionEntity> executions = executionEntityManager.FindChildExecutionsByProcessInstanceId(processInstanceId); int activeExecutions = 0; foreach (IExecutionEntity execution in executions) { if (execution.IsActive && !processInstanceId.Equals(execution.Id)) { activeExecutions++; } } return(activeExecutions); }
protected internal virtual void ExecuteInclusiveGatewayLogic(IExecutionEntity execution) { ICommandContext commandContext = Context.CommandContext; IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager; LockFirstParentScope(execution); ICollection <IExecutionEntity> allExecutions = executionEntityManager.FindChildExecutionsByProcessInstanceId(execution.ProcessInstanceId); IEnumerator <IExecutionEntity> executionIterator = allExecutions.GetEnumerator(); bool oneExecutionCanReachGateway = false; while (!oneExecutionCanReachGateway && executionIterator.MoveNext()) { IExecutionEntity executionEntity = executionIterator.Current; if (!executionEntity.ActivityId.Equals(execution.CurrentActivityId)) { bool canReachGateway = ExecutionGraphUtil.IsReachable(execution.ProcessDefinitionId, executionEntity.ActivityId, execution.CurrentActivityId); if (canReachGateway) { oneExecutionCanReachGateway = true; } } else if (executionEntity.ActivityId.Equals(execution.CurrentActivityId) && executionEntity.IsActive) { // Special case: the execution has reached the inc gw, but the operation hasn't been executed yet for that execution oneExecutionCanReachGateway = true; } } // If no execution can reach the gateway, the gateway activates and executes fork behavior if (!oneExecutionCanReachGateway) { logger.LogDebug("Inclusive gateway cannot be reached by any execution and is activated"); // Kill all executions here (except the incoming) ICollection <IExecutionEntity> executionsInGateway = executionEntityManager.FindInactiveExecutionsByActivityIdAndProcessInstanceId(execution.CurrentActivityId, execution.ProcessInstanceId); foreach (IExecutionEntity executionEntityInGateway in executionsInGateway) { if (!executionEntityInGateway.Id.Equals(execution.Id)) { commandContext.HistoryManager.RecordActivityEnd(executionEntityInGateway, null); executionEntityManager.DeleteExecutionAndRelatedData(executionEntityInGateway, null, false); } } // Leave commandContext.Agenda.PlanTakeOutgoingSequenceFlowsOperation(execution, true); } }
public virtual object Execute(ICommandContext commandContext) { // check that the new process definition is just another version of the same // process definition that the process instance is using IExecutionEntityManager executionManager = commandContext.ExecutionEntityManager; IExecutionEntity processInstance = executionManager.FindById <IExecutionEntity>(new KeyValuePair <string, object>("id", processInstanceId)); if (processInstance == null) { throw new ActivitiObjectNotFoundException("No process instance found for id = '" + processInstanceId + "'.", typeof(IProcessInstance)); } else if (!processInstance.ProcessInstanceType) { throw new ActivitiIllegalArgumentException("A process instance id is required, but the provided id " + "'" + processInstanceId + "' " + "points to a child execution of process instance " + "'" + processInstance.ProcessInstanceId + "'. " + "Please invoke the " + this.GetType().Name + " with a root execution id."); } DeploymentManager deploymentCache = commandContext.ProcessEngineConfiguration.DeploymentManager; IProcessDefinition currentProcessDefinition = deploymentCache.FindDeployedProcessDefinitionById(processInstance.ProcessDefinitionId); IProcessDefinition newProcessDefinition = deploymentCache.FindDeployedProcessDefinitionByKeyAndVersionAndTenantId(currentProcessDefinition.Key, processDefinitionVersion, currentProcessDefinition.TenantId); ValidateAndSwitchVersionOfExecution(commandContext, processInstance, newProcessDefinition); // switch the historic process instance to the new process definition version commandContext.HistoryManager.RecordProcessDefinitionChange(processInstanceId, newProcessDefinition.Id); // switch all sub-executions of the process instance to the new process definition version ICollection <IExecutionEntity> childExecutions = executionManager.FindChildExecutionsByProcessInstanceId(processInstanceId); foreach (IExecutionEntity executionEntity in childExecutions) { ValidateAndSwitchVersionOfExecution(commandContext, executionEntity, newProcessDefinition); } return(null); }