public async Task <long> Delete(Guid id)
        {
            // 删除指定id的状态机实例, 因为有并发键需要重试多次
            StateMachineInstanceEntity stateMachineInstanceEntity = null;

            for (int from = 0; from <= ConcurrencyErrorMaxRetryTimes; ++from)
            {
                stateMachineInstanceEntity = await _repository.QueryAsync(q =>
                                                                          q.FirstOrDefaultAsyncTestable(x => x.Id == id));

                if (stateMachineInstanceEntity == null)
                {
                    return(0);
                }
                _repository.Remove(stateMachineInstanceEntity);
                try
                {
                    await _repository.SaveChangesAsync();

                    break;
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (from == ConcurrencyErrorMaxRetryTimes)
                    {
                        throw;
                    }
                    await Task.Delay(1);
                }
            }
            return(1);
        }
        private async Task <(StateMachineEntity, StateMachineInstanceEntity)> PutTestInstance()
        {
            var putDto = await PutSimpleDataSet();

            var stateMachineRepository         = new DummyRepository <StateMachineEntity, Guid>(_storage);
            var stateMachineInstanceRepository = new DummyRepository <StateMachineInstanceEntity, Guid>(_storage);
            var stateMachineEntity             = await stateMachineRepository.QueryNoTrackingAsync(q =>
                                                                                                   q.FirstOrDefaultAsyncTestable(x => x.Name == putDto.Name));

            var stateMachineInstanceEntity = new StateMachineInstanceEntity()
            {
                Id           = PrimaryKeyUtils.Generate <Guid>(),
                Name         = putDto.Name,
                Status       = StateMachineStatus.Running,
                Stage        = StateMachineBase.InitialStage,
                InitialBlobs = putDto.InitialBlobs,
                Limitation   = _configuration.Limitation,
                Parameters   = new Dictionary <string, string>()
                {
                    { "Host", "http://localhost:8888" }
                },
                Priority = 123,
                FromManagementService = _configuration.Name,
                ExecutionKey          = PrimaryKeyUtils.Generate <Guid>().ToString(),
                StartTime             = DateTime.UtcNow
            };
            await stateMachineInstanceRepository.AddAsync(stateMachineInstanceEntity);

            await stateMachineInstanceRepository.SaveChangesAsync();

            return(stateMachineEntity, stateMachineInstanceEntity);
        }
        public async Task <StateMachineInstancePutResultDto> Put(StateMachineInstancePutDto dto)
        {
            // 获取name对应的状态机代码
            var stateMachineEntity = await _stateMachineRepository.QueryNoTrackingAsync(q =>
                                                                                        q.FirstOrDefaultAsyncTestable(x => x.Name == dto.Name));

            if (stateMachineEntity == null)
            {
                return(StateMachineInstancePutResultDto.NotFound("state machine not found"));
            }
            // 创建状态机实例
            var stateMachineInstanceEntity = new StateMachineInstanceEntity()
            {
                Id            = PrimaryKeyUtils.Generate <Guid>(),
                Name          = stateMachineEntity.Name,
                Status        = StateMachineStatus.Running,
                Stage         = StateMachineBase.InitialStage,
                StartedActors = new List <ActorInfo>(),
                InitialBlobs  = dto.InitialBlobs ?? new BlobInfo[0],
                Limitation    = ContainerLimitation.Default
                                .WithDefaults(dto.Limitation)
                                .WithDefaults(stateMachineEntity.Limitation)
                                .WithDefaults(_configuration.Limitation),
                Parameters            = dto.Parameters,
                Priority              = dto.Priority,
                FromManagementService = _configuration.Name,
                ReRunTimes            = 0,
                Exception             = null,
                ExecutionKey          = PrimaryKeyUtils.Generate <Guid>().ToString(),
                StartTime             = DateTime.UtcNow,
                EndTime = null
            };
            var stateMachineInstance = await _stateMachineInstanceStore.CreateInstance(
                stateMachineEntity, stateMachineInstanceEntity);

            // 添加状态机实例到数据库
            await _repository.AddAsync(stateMachineInstanceEntity);

            await _repository.SaveChangesAsync();

            // 运行状态机, 从这里开始会在后台运行
#pragma warning disable CS4014
            _stateMachineInstanceStore.RunInstance(stateMachineInstance);
#pragma warning restore CS4014
            return(StateMachineInstancePutResultDto.Success(
                       Mapper.Map <StateMachineInstanceEntity, StateMachineInstanceOutputDto>(stateMachineInstanceEntity)));
        }
        public async Task <StateMachineInstancePatchResultDto> Patch(Guid id, StateMachineInstancePatchDto dto)
        {
            // 更新阶段, 参数和并发键
            StateMachineInstanceEntity stateMachineInstanceEntity = null;
            StateMachineEntity         stateMachineEntity         = null;

            for (int from = 0; from <= ConcurrencyErrorMaxRetryTimes; ++from)
            {
                stateMachineInstanceEntity = await _repository.QueryAsync(q =>
                                                                          q.FirstOrDefaultAsyncTestable(x => x.Id == id));

                if (stateMachineInstanceEntity == null)
                {
                    return(StateMachineInstancePatchResultDto.NotFound("state machine instance not found"));
                }
                stateMachineEntity = await _stateMachineRepository.QueryNoTrackingAsync(q =>
                                                                                        q.FirstOrDefaultAsyncTestable(x => x.Name == stateMachineInstanceEntity.Name));

                if (stateMachineEntity == null)
                {
                    return(StateMachineInstancePatchResultDto.NotFound("state machine not found"));
                }
                stateMachineInstanceEntity.Status                = StateMachineStatus.Running;
                stateMachineInstanceEntity.Stage                 = dto.Stage ?? StateMachineBase.InitialStage;
                stateMachineInstanceEntity.ExecutionKey          = PrimaryKeyUtils.Generate <Guid>().ToString();
                stateMachineInstanceEntity.FromManagementService = _configuration.Name;
                stateMachineInstanceEntity.StartTime             = DateTime.UtcNow; // 柚子大姐要求
                if (dto.Parameters != null)
                {
                    var parameters = stateMachineInstanceEntity.Parameters;
                    foreach (var pair in dto.Parameters)
                    {
                        parameters[pair.Key] = pair.Value;
                    }
                    stateMachineInstanceEntity.Parameters = parameters;
                }
                try
                {
                    await _repository.SaveChangesAsync();

                    break;
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (from == ConcurrencyErrorMaxRetryTimes)
                    {
                        throw;
                    }
                    await Task.Delay(1);
                }
            }
            // 创建状态机实例
            var stateMachineInstance = await _stateMachineInstanceStore.CreateInstance(
                stateMachineEntity, stateMachineInstanceEntity);

            // 运行状态机, 从这里开始会在后台运行
#pragma warning disable CS4014
            _stateMachineInstanceStore.RunInstance(stateMachineInstance);
#pragma warning restore CS4014
            return(StateMachineInstancePatchResultDto.Success());
        }