Ejemplo n.º 1
0
        public void SetUp()
        {
            _container = new Container(x => x.For(typeof(IEventQueueFactory <>)).Use(typeof(DefaultEventQueueFactory <>)));
            var services = new StructureMapServiceLocator(_container);

            _factory = new EventQueueFactory(services);
        }
Ejemplo n.º 2
0
        private async Task <int> SaveChangesAsync(DbContext context, CancellationToken cancellationToken = default)
        {
            Validate.IsNotNull(context);

            var success = false;
            var rows    = default(int);

            var aggregates = _context.GetPendingAggregates().ToArray();

            await ProcessPreTransactionEvents().ConfigureAwait(false);

            AzureEfConfiguration.SuspendExecutionStrategy = true;

            var operation = new Func <Task>
                            (
                async() =>
            {
                using (var transaction = context.Database.BeginTransaction())
                {
                    try
                    {
                        rows = await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
                        transaction.Commit();
                        success = true;
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();

                        if (ex is DBConcurrencyException || ex is OptimisticConcurrencyException)
                        {
                            // NOTE:
                            // For concurrency exceptions we want to ensure the
                            // entities are not cached in the context so we can
                            // stop the same error being raised indefinitely.

                            await RefreshAllAsync(cancellationToken).ConfigureAwait(false);
                        }

                        throw;
                    }
                }
            }
                            );

            await new SqlAzureExecutionStrategy().Execute(operation).ConfigureAwait(false);

            AzureEfConfiguration.SuspendExecutionStrategy = false;

            if (success)
            {
                await ProcessPostTransactionEvents().ConfigureAwait(false);
            }

            async Task ProcessPreTransactionEvents()
            {
                IEventQueue CreateQueue()
                {
                    return(EventQueueFactory.CreatePreTransactionEventQueue(aggregates));
                }

                var eventQueue = CreateQueue();

                while (false == eventQueue.IsEmpty())
                {
                    var preProcessItems = eventQueue.ToList();

                    await ProcessEventQueue(eventQueue, true).ConfigureAwait(false);

                    aggregates = _context.GetPendingAggregates().ToArray();
                    eventQueue = CreateQueue().Remove(preProcessItems);
                }
            }

            async Task ProcessPostTransactionEvents()
            {
                var eventQueue = EventQueueFactory.CreatePostTransactionEventQueue(aggregates);

                foreach (var aggregate in aggregates)
                {
                    if (aggregate.UnpublishedEvents != null)
                    {
                        aggregate.UnpublishedEvents.Clear();
                    }
                }

                await ProcessEventQueue(eventQueue).ConfigureAwait(false);
            }

            return(rows);
        }