public Enumerator(RemovableEntitiesCollectHandlerCollection collection)
 {
     _delegateInfo = new[]
     {
         RemovableEntitiesCollectHandlerInfo.Create(nameof(Failure), collection.CollectAutobookFailures),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(Recommendation), collection.CollectRecommendationProcessors),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(ResultsFile), collection.CollectResultFiles),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(SmoothFailure), collection.CollectSmoothFailures),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(Pass), collection.CollectScenarioPasses),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(ScenarioCampaignResult), collection.CollectScenarioCampaignResult),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(ScenarioCampaignFailure), collection.CollectScenarioCampaignFailures),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(ScenarioCampaignMetric), collection.CollectScenarioCampaignMetrics),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(AutoBookTask), collection.CollectAutobookTasks),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(PipelineAuditEvent), collection.CollectPipelineAuditEvents),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(AutoBookTaskReport), collection.CollectAutobookTaskReports),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(ScenarioResult), collection.CollectScenarioResults),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(Scenario), collection.CollectScenarios),
         RemovableEntitiesCollectHandlerInfo.Create(nameof(Run), collection.CollectRuns)
     };
 }
Exemplo n.º 2
0
        protected override async Task DeleteRunDataAsync(IReadOnlyCollection <RunDeletionInfo> runDeletionInfos,
                                                         CancellationToken cancellationToken)
        {
            var allRunIds      = runDeletionInfos.Select(r => r.RunId).ToArray();
            var allScenarioIds = runDeletionInfos.SelectMany(r => r.ScenarioIds).Distinct().ToArray();

            var actionBlock =
                new ActionBlock <RemovableEntitiesCollectHandlerInfo>(RemoveEntitiesAsync,
                                                                      new ExecutionDataflowBlockOptions
            {
                CancellationToken      = cancellationToken,
                MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
            });

            var collectHandlerCollection =
                new RemovableEntitiesCollectHandlerCollection(allRunIds, allScenarioIds, cancellationToken);

            foreach (var itemInfo in collectHandlerCollection.Where(x => x.EntityName != nameof(Run)))
            {
                _ = await actionBlock.SendAsync(itemInfo, cancellationToken).ConfigureAwait(false);
            }

            actionBlock.Complete();

            await actionBlock.Completion.AggregateExceptions().ConfigureAwait(false);

            // removes Run entities only when all dependent entities have been removed successfully
            var runCollectHandlerInfo = collectHandlerCollection.FirstOrDefault(x => x.EntityName == nameof(Run));

            if (!(runCollectHandlerInfo is null))
            {
                await RemoveEntitiesAsync(runCollectHandlerInfo).ConfigureAwait(false);
            }

            #region Local functions

            async Task RemoveEntitiesAsync(RemovableEntitiesCollectHandlerInfo handlerInfo)
            {
                try
                {
                    using (var dbContext = _dbContextFactory.Create())
                    {
                        var entities = await handlerInfo.CollectFunc(dbContext).ConfigureAwait(false);

                        foreach (var entity in entities)
                        {
                            dbContext.Specific.Attach(entity).State = EntityState.Deleted;
                        }

                        while (true)
                        {
                            try
                            {
                                await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

                                break;
                            }
                            catch (DbUpdateConcurrencyException ex)
                            {
                                if (ex.Entries.Count == 0)
                                {
                                    throw;
                                }

                                foreach (var entry in ex.Entries)
                                {
                                    entry.State = EntityState.Detached;
                                }
                            }
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    var formatterRunInfo = allRunIds.Length == 1
                        ? $"run with id '{allRunIds.First()}'"
                        : $"{allRunIds.Length} runs ({string.Join(", ", allRunIds.Select(x => $"'{x}'"))})";

                    throw new RunCleaningException(
                              $"Deletion of {formatterRunInfo} has been failed while removing '{handlerInfo.EntityName}' entities. See inner exception for more details.",
                              ex);
                }
            }

            #endregion Local functions
        }