/**********************************************************************************/
            // 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();
                }
            }