protected internal override PvmExecutionImpl EventNotificationsStarted(PvmExecutionImpl execution) { execution.IncrementSequenceCounter(); // hack around execution tree structure not being in sync with activity instance concept: // if we end a scope activity, take remembered activity instance from parent and set on // execution before calling END listeners. var parent = execution.Parent; IPvmActivity activity = execution.Activity; if ((parent != null) && execution.IsScope && (activity != null) && activity.IsScope && (activity.ActivityBehavior is ICompositeActivityBehavior || (CompensationBehavior.IsCompensationThrowing(execution) && !LegacyBehavior.IsCompensationThrowing(execution)))) { Log.DebugLeavesActivityInstance(execution, execution.ActivityInstanceId); // use remembered activity instance id from parent execution.ActivityInstanceId = parent.ActivityInstanceId; // make parent go one scope up. parent.LeaveActivityInstance(); } return(execution); }
protected internal virtual bool CanHaveChildScopes(PvmExecutionImpl execution) { IPvmActivity activity = execution.Activity; return(activity.ActivityBehavior is ICompositeActivityBehavior || CompensationBehavior.IsCompensationThrowing(execution)); }
/// <summary> /// event-scope executions are not considered in this mapping and must be ignored /// </summary> protected internal virtual bool IsLeaf(IActivityExecution execution) { if (CompensationBehavior.IsCompensationThrowing((PvmExecutionImpl)execution)) { return(true); } return(!execution.IsEventScope && execution.NonEventScopeExecutions.Count == 0); }
/// <summary> /// event-scope executions are not considered in this mapping and must be ignored /// </summary> protected internal virtual bool isLeaf(ExecutionEntity execution) { if (CompensationBehavior.isCompensationThrowing(execution)) { return(true); } else { return(!execution.EventScope && execution.NonEventScopeExecutions.Count == 0); } }
protected internal override void EventNotificationsCompleted(PvmExecutionImpl execution) { IPvmActivity activity = execution.Activity; if (execution.IsScope && (ExecutesNonScopeActivity(execution) || IsAsyncBeforeActivity(execution)) && !CompensationBehavior.executesNonScopeCompensationHandler(execution)) { // case this is a scope execution and the activity is not a scope execution.LeaveActivityInstance(); execution.Activity = (GetFlowScopeActivity(activity)); execution.PerformOperation(PvmAtomicOperationFields.DeleteCascadeFireActivityEnd); } else { if (execution.IsScope) { execution.Destroy(); } // remove this execution and its concurrent parent (if exists) execution.Remove(); var continueRemoval = !execution.IsDeleteRoot; if (continueRemoval) { var propagatingExecution = execution.Parent; if ((propagatingExecution != null) && !propagatingExecution.IsScope && !propagatingExecution.HasChildren()) { propagatingExecution.Remove(); continueRemoval = !propagatingExecution.IsDeleteRoot; propagatingExecution = propagatingExecution.Parent; } if (continueRemoval) { if (propagatingExecution != null) { // continue deletion with the next scope execution // set activity on parent in case the parent is an inactive scope execution and activity has been set to 'null'. if ((propagatingExecution.Activity == null) && (activity != null) && (activity.FlowScope != null)) { propagatingExecution.Activity = (GetFlowScopeActivity(activity)); } ((PvmExecutionImpl)propagatingExecution).PerformOperation(PvmAtomicOperationFields.DeleteCascade); } } } } }
protected internal virtual bool isAncestorCompensationThrowing(ActivityExecution execution) { ActivityExecution parent = execution.Parent; while (parent != null) { if (CompensationBehavior.isCompensationThrowing((PvmExecutionImpl)parent)) { return(true); } parent = parent.Parent; } return(false); }
protected internal virtual IList <ExecutionEntity> FilterLeaves(IList <ExecutionEntity> executionList) { IList <ExecutionEntity> leaves = new List <ExecutionEntity>(); foreach (var execution in executionList) { // although executions executing throwing compensation events are not leaves in the tree, // they are treated as leaves since their child executions are logical children of their parent scope execution if (execution.NonEventScopeExecutions.Count == 0 || CompensationBehavior.IsCompensationThrowing(execution)) { leaves.Add(execution); } } return(leaves); }
protected internal virtual void InitActivityInstanceEvent(HistoricActivityInstanceEventEntity evt, ExecutionEntity execution, IHistoryEventType eventType) { IPvmScope eventSource = execution.Activity; if (eventSource == null) { eventSource = (IPvmScope)execution.EventSource; } string activityInstanceId = execution.ActivityInstanceId; string parentActivityInstanceId = null; ExecutionEntity parentExecution = (ExecutionEntity)execution.Parent; if (parentExecution != null && CompensationBehavior.IsCompensationThrowing(parentExecution) && execution.Activity != null) { parentActivityInstanceId = CompensationBehavior.GetParentActivityInstanceId(execution); } else { parentActivityInstanceId = execution.ParentActivityInstanceId; } InitActivityInstanceEvent(evt, execution, eventSource, activityInstanceId, parentActivityInstanceId, eventType); }
public virtual IActivityInstance Execute(CommandContext commandContext) { EnsureUtil.EnsureNotNull("processInstanceId", ProcessInstanceId); IList <ExecutionEntity> executionList = LoadProcessInstance(ProcessInstanceId, commandContext); if (executionList.Count == 0) { return(null); } CheckGetActivityInstance(ProcessInstanceId, commandContext); IList <ExecutionEntity> nonEventScopeExecutions = FilterNonEventScopeExecutions(executionList); IList <ExecutionEntity> leaves = FilterLeaves(nonEventScopeExecutions);//.OrderBy(m => m.Id).ToList(); // Leaves must be ordered in a predictable way (e.g. by ID) // in order to return a stable execution tree with every repeated invocation of this command. // For legacy process instances, there may miss scope executions for activities that are now a scope. // In this situation, there may be multiple scope candidates for the same instance id; which one // can depend on the order the leaves are iterated. OrderById(leaves); ExecutionEntity processInstance = FilterProcessInstance(executionList); if (processInstance.IsEnded) { return(null); } //create act instance for process instance ActivityInstanceImpl processActInst = CreateActivityInstance(processInstance, processInstance.ProcessDefinition, ProcessInstanceId, null); IDictionary <string, ActivityInstanceImpl> activityInstances = new Dictionary <string, ActivityInstanceImpl>(); activityInstances[ProcessInstanceId] = processActInst; IDictionary <string, TransitionInstanceImpl> transitionInstances = new Dictionary <string, TransitionInstanceImpl>(); foreach (ExecutionEntity leaf in leaves) { // skip leafs without activity, e.g. if only the process instance exists after cancellation // it will not have an activity set if (leaf.Activity == null) { continue; } IDictionary <ScopeImpl, PvmExecutionImpl> activityExecutionMapping = leaf.CreateActivityExecutionMapping(); IDictionary <ScopeImpl, PvmExecutionImpl> scopeInstancesToCreate = new Dictionary <ScopeImpl, PvmExecutionImpl>(activityExecutionMapping); // create an activity/transition instance for each leaf that executes a non-scope activity // and does not throw compensation if (leaf.ActivityInstanceId != null) { if (!CompensationBehavior.IsCompensationThrowing(leaf) || LegacyBehavior.IsCompensationThrowing(leaf, activityExecutionMapping)) { string parentActivityInstanceId = null; parentActivityInstanceId = activityExecutionMapping[leaf.Activity.FlowScope].ParentActivityInstanceId; ActivityInstanceImpl leafInstance = CreateActivityInstance(leaf, (ScopeImpl)leaf.Activity, leaf.ActivityInstanceId, parentActivityInstanceId); activityInstances[leafInstance.Id] = leafInstance; scopeInstancesToCreate.Remove((ScopeImpl)leaf.Activity); } } else { TransitionInstanceImpl transitionInstance = CreateTransitionInstance(leaf); transitionInstances[transitionInstance.Id] = transitionInstance; scopeInstancesToCreate.Remove((ScopeImpl)leaf.Activity); } LegacyBehavior.RemoveLegacyNonScopesFromMapping(scopeInstancesToCreate); scopeInstancesToCreate.Remove(leaf.ProcessDefinition); // create an activity instance for each scope (including compensation throwing executions) foreach (KeyValuePair <ScopeImpl, PvmExecutionImpl> scopeExecutionEntry in scopeInstancesToCreate) { ScopeImpl scope = scopeExecutionEntry.Key; PvmExecutionImpl scopeExecution = scopeExecutionEntry.Value; string activityInstanceId = null; string parentActivityInstanceId = null; activityInstanceId = scopeExecution.ParentActivityInstanceId; parentActivityInstanceId = activityExecutionMapping[scope.FlowScope].ParentActivityInstanceId; if (activityInstances.ContainsKey(activityInstanceId)) { continue; } else { // regardless of the tree structure (compacted or not), the scope's activity instance id // is the activity instance id of the parent execution and the parent activity instance id // of that is the actual parent activity instance id ActivityInstanceImpl scopeInstance = CreateActivityInstance(scopeExecution, scope, activityInstanceId, parentActivityInstanceId); activityInstances[activityInstanceId] = scopeInstance; } } } LegacyBehavior.RepairParentRelationships(activityInstances.Values, ProcessInstanceId); PopulateChildInstances(activityInstances, transitionInstances); return(processActInst); }
protected internal override void eventNotificationsCompleted(PvmExecutionImpl execution) { PvmActivity activity = execution.getActivity(); if (execution.Scope && (executesNonScopeActivity(execution) || isAsyncBeforeActivity(execution)) && !CompensationBehavior.executesNonScopeCompensationHandler(execution)) { execution.removeAllTasks(); // case this is a scope execution and the activity is not a scope execution.leaveActivityInstance(); execution.setActivity(getFlowScopeActivity(activity)); execution.performOperation(PvmAtomicOperation_Fields.DELETE_CASCADE_FIRE_ACTIVITY_END); } else { if (execution.Scope) { execution.destroy(); } // remove this execution and its concurrent parent (if exists) execution.remove(); bool continueRemoval = !execution.DeleteRoot; if (continueRemoval) { PvmExecutionImpl propagatingExecution = execution.Parent; if (propagatingExecution != null && !propagatingExecution.Scope && !propagatingExecution.hasChildren()) { propagatingExecution.remove(); continueRemoval = !propagatingExecution.DeleteRoot; propagatingExecution = propagatingExecution.Parent; } if (continueRemoval) { if (propagatingExecution != null) { // continue deletion with the next scope execution // set activity on parent in case the parent is an inactive scope execution and activity has been set to 'null'. if (propagatingExecution.getActivity() == null && activity != null && activity.FlowScope != null) { propagatingExecution.setActivity(getFlowScopeActivity(activity)); } } } } } }