Пример #1
0
        protected string makeSagaIdAndStepKey <FormType>(string sagaId,
                                                         SimpleSaga <FormType> saga, SagaStep step) where FormType : class, SagaData
        {
            var stepKey = saga.GetSagaDefinition().KeyOfStep(step);

            return($"{sagaId}-{stepKey}");
        }
Пример #2
0
        public async Task CompensationDone <FormType>(SimpleSaga <FormType> saga,
                                                      SagaStep step, string sagaId, SagaData form) where FormType : class, SagaData
        {
            var stepKey = saga.GetSagaDefinition().KeyOfStep(step);

            sagaDoneCompensationSteps.AddOrUpdate(sagaId, new HashSet <string>()
            {
                stepKey
            }, (_, oldSet) => {
                oldSet.Add(stepKey);
                return(oldSet);
            });
            var doneCompensationSteps        = sagaDoneCompensationSteps[sagaId];
            var needDoCompensationStepsCount = saga.GetSagaDefinition().Steps.Count(); // 此sagaId需要执行补偿的steps count

            if (doneCompensationSteps.Count() >= needDoCompensationStepsCount)
            {
                // sagaStates[sagaId] = SagaState.COMPENSATION_DONE;
                var oldInfo = _sagaInfos[sagaId];
                if (oldInfo.State != SagaState.COMPENSATION_DONE)
                {
                    if (!_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(SagaState.COMPENSATION_DONE), oldInfo))
                    {
                        throw new SagaAbortException($"saga {sagaId} CompensationDone error because of state update conflict");
                    }
                }
                saga.OnSagaRolledBack(sagaId, form);
            }
            return;
        }
Пример #3
0
        public SagaDefinitionBuilder <FormType> Step()
        {
            var sagaStep = new SagaStep();

            buildingStep = sagaStep;
            building.AddStep(sagaStep);
            return(this);
        }
Пример #4
0
        protected int SINGLE_STEP_COMPENSATION_TRY_COUNT = 3; // 一个步骤的补偿任务最多重试的次数

        public Task CompensationException <FormType>(SimpleSaga <FormType> saga,
                                                     SagaStep step, string sagaId, SagaData form, Exception e) where FormType : class, SagaData
        {
            // 记录失败信息和失败次数
            var key = makeSagaIdAndStepKey(sagaId, saga, step);

            sagaStepsCompensationFailCount.AddOrUpdate(key, 1, (_, oldCount) => oldCount + 1);
            var failCount = sagaStepsCompensationFailCount[key];

            if (failCount >= SINGLE_STEP_COMPENSATION_TRY_COUNT)
            {
                // 这个step的补偿任务执行失败次数太多了
                Console.WriteLine($"saga {sagaId} step {saga.GetSagaDefinition().KeyOfStep(step)} compensation fail too many times error {e.Message}");
                // sagaStates.TryUpdate(sagaId, SagaState.COMPENSATION_FAIL, SagaState.COMPENSATION_DOING);
                while (true)
                {
                    if (!_sagaInfos.ContainsKey(sagaId))
                    {
                        break;
                    }
                    var oldInfo = _sagaInfos[sagaId];
                    if (oldInfo.State.IsEndState())
                    {
                        break;
                    }
                    if (_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(SagaState.COMPENSATION_FAIL), oldInfo))
                    {
                        break;
                    }
                }
            }
            else
            {
                while (true)
                {
                    if (!_sagaInfos.ContainsKey(sagaId))
                    {
                        break;
                    }
                    var oldInfo = _sagaInfos[sagaId];
                    if (oldInfo.State.IsEndState() || oldInfo.State == SagaState.COMPENSATION_ERROR)
                    {
                        break;
                    }
                    if (_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(SagaState.COMPENSATION_ERROR), oldInfo))
                    {
                        break;
                    }
                }
            }
            return(Task.CompletedTask);
        }
Пример #5
0
        public string KeyOfStep(SagaStep step)
        {
            var key = step.Key();

            if (key != null)
            {
                return(key);
            }
            var i = 0;

            foreach (var s in Steps)
            {
                if (s == step)
                {
                    return(i.ToString());
                }
                i++;
            }
            return(step.GetType().FullName);
        }
Пример #6
0
 public void AddStep(SagaStep step)
 {
     _steps.Add(step);
 }