/**********************************************************************************/ // See https://maginot.atlassian.net/wiki/display/DDW/New+container+execution+logic for details public async Task Run() { while (_callStack.Count > 0) { if (_callStack.Count > MaxStackSize) { throw new Exception($"Container execution stack overflow. Container: {_container.Id}. PlanId: {_container.PlanId}."); } var topFrame = _callStack.TopFrame; var currentNode = _uow.PlanRepository.GetById <PlanNodeDO>(topFrame.NodeId); if (currentNode == null) { throw new Exception($"PlanNode with id: {topFrame.NodeId} was not found. Container: {_container.Id}. PlanId: {_container.PlanId}."); } try { try { using (var payloadStorage = _crate.UpdateStorage(() => _container.CrateStorage)) { _operationalState = GetOperationalState(payloadStorage); _operationalState.CallStack = _callStack; // reset current activity response _operationalState.CurrentActivityResponse = null; // update container's payload payloadStorage.Flush(); if (!_activityRateLimiter.CheckActivityExecutionRate(currentNode.Fr8AccountId)) { _callStack.Clear(); _container.State = State.Failed; return; } if (topFrame.CurrentActivityExecutionPhase == OperationalStateCM.ActivityExecutionPhase.WasNotExecuted) { await ExecuteNode(currentNode, payloadStorage, ActivityExecutionMode.InitialRun); topFrame.CurrentActivityExecutionPhase = OperationalStateCM.ActivityExecutionPhase.ProcessingChildren; // process op codes if (!ProcessActivityResponse(_operationalState.CurrentActivityResponse, OperationalStateCM.ActivityExecutionPhase.WasNotExecuted, topFrame)) { break; } continue; } var nextChild = GetNextChildActivity(topFrame, currentNode); // if there is a child that has not being executed yet - add it for execution by pushing to the call stack if (nextChild != null) { AddNodeForExecution(nextChild.Id); topFrame.CurrentChildId = nextChild.Id; } // or run current activity in ReturnFromChildren mode else { if (currentNode.ChildNodes.Count > 0) { await ExecuteNode(currentNode, payloadStorage, ActivityExecutionMode.ReturnFromChildren); } _callStack.RemoveTopFrame(); // process op codes if (!ProcessActivityResponse(_operationalState.CurrentActivityResponse, OperationalStateCM.ActivityExecutionPhase.ProcessingChildren, topFrame)) { break; } } } } catch { _container.State = State.Failed; throw; } finally { _uow.SaveChanges(); } } catch (ErrorResponseException e) { throw new ActivityExecutionException(e.ContainerDTO, Mapper.Map <ActivityDO, ActivityDTO>((ActivityDO)currentNode), e.Message, e); } catch (InvalidTokenRuntimeException) { throw; } catch (Exception e) { var curActivity = currentNode as ActivityDO; if (curActivity != null) { var activityDTO = Mapper.Map <ActivityDO, ActivityDTO>(curActivity); activityDTO.ActivityTemplate = Mapper.Map <ActivityTemplateSummaryDTO>(_uow.ActivityTemplateRepository.GetByKey(curActivity.ActivityTemplateId)); throw new ActivityExecutionException(Mapper.Map <ContainerDO, ContainerDTO>(_container), activityDTO, string.Empty, e); } throw; } } if (_container.State == State.Executing) { _container.State = State.Completed; _uow.SaveChanges(); } }