/**********************************************************************************/ private void AddNodeForExecution(Guid nodeId) { var node = _uow.PlanRepository.GetById <PlanNodeDO>(nodeId); string nodeName = "undefined"; if (node is ActivityDO) { var activityTemplate = _uow.ActivityTemplateRepository.GetByKey(((ActivityDO)node).ActivityTemplateId); nodeName = "Activity: " + activityTemplate.Name + " Version:" + activityTemplate.Version; } if (node is SubplanDO) { nodeName = "Subplan: " + ((SubplanDO)node).Name; } var frame = new OperationalStateCM.StackFrame { NodeId = nodeId, NodeName = nodeName, LocalData = _bypassData }; _callStack.PushFrame(frame); _bypassData = null; }
// Previously we were using CurrentActivityId to track container execution. // To better accomodate new requirements we changed CurrentActivityId to the Call Stack. // But we still can have pending plans in our DB that were created using CurrentActivityId as the main driven logic. // To be able to continue executuion of those plans we have the following method. // This methods takes CurrentActivityId of the plan and build a call stack using this Id and Plan structure. // As the result we will have correct call stack for the plan that was suspended at the node CurrentActivityId. // After call stack restoration CurrentActivityId is no longer needed. private OperationalStateCM.ActivityCallStack RecoverCallStack(IUnitOfWork uow, ContainerDO curContainerDo) { var node = uow.PlanRepository.GetById <PlanNodeDO>(curContainerDo.CurrentActivityId); if (node == null) { throw new InvalidOperationException($"Failed to restore call stack from CurrentPlanNodeId. Node {curContainerDo.CurrentActivityId} was not found."); } var callStack = new OperationalStateCM.ActivityCallStack(); var pathToRoot = new List <OperationalStateCM.StackFrame>(); while (node != null && !(node is PlanDO)) { string nodeName = "undefined"; if (node is ActivityDO) { var activityTemplate = uow.ActivityTemplateRepository.GetByKey(((ActivityDO)node).ActivityTemplateId); nodeName = "Activity: " + activityTemplate.Name + " Version:" + activityTemplate.Version; } if (node is SubplanDO) { nodeName = "Subplan: " + ((SubplanDO)node).Name; } pathToRoot.Add(new OperationalStateCM.StackFrame { NodeName = nodeName, CurrentActivityExecutionPhase = OperationalStateCM.ActivityExecutionPhase.ProcessingChildren, NodeId = node.Id }); node = node.ParentPlanNode; } for (int i = pathToRoot.Count - 1; i >= 1; i--) { pathToRoot[i].CurrentChildId = pathToRoot[i - 1].NodeId; callStack.PushFrame(pathToRoot[i]); } callStack.PushFrame(pathToRoot[0]); callStack.TopFrame.CurrentActivityExecutionPhase = OperationalStateCM.ActivityExecutionPhase.WasNotExecuted; using (var storage = _crate.UpdateStorage(() => curContainerDo.CrateStorage)) { var operationalState = storage.CrateContentsOfType <OperationalStateCM>().Single(); operationalState.CallStack = callStack; } curContainerDo.CurrentActivityId = null; curContainerDo.NextActivityId = null; curContainerDo.CurrentPlanNode = null; curContainerDo.NextRouteNode = null; return(callStack); }