Example #1
0
        public async Task <IActionResult> DepositMessage()
        {
            var greetingAsync = new GreetingAsyncEvent("Deposit Hello from the web");
            var greeting      = new GreetingEvent("Deposit Hello from the web");

            await _commandProcessor.DepositPostAsync(greetingAsync);

            _context.Greetings.Add(greeting);
            _context.GreetingsAsync.Add(greetingAsync);
            await _context.SaveChangesAsync();

            _commandProcessor.DepositPost(greeting);
            await _commandProcessor.DepositPostAsync(greetingAsync);

            return(View("Index"));
        }
Example #2
0
        public override async Task <GreetingMade> HandleAsync(GreetingMade @event, CancellationToken cancellationToken = default(CancellationToken))
        {
            var posts = new List <Guid>();

            var tx = await _uow.Database.BeginTransactionAsync(cancellationToken);

            try
            {
                var salutation = new Salutation(@event.Greeting);

                _uow.Salutations.Add(salutation);

                posts.Add(await _postBox.DepositPostAsync(new SalutationReceived(DateTimeOffset.Now), cancellationToken: cancellationToken));

                await _uow.SaveChangesAsync(cancellationToken);

                await tx.CommitAsync(cancellationToken);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);

                await tx.RollbackAsync(cancellationToken);

                Console.WriteLine("Salutation analytical record not saved");

                throw;
            }

            await _postBox.ClearOutboxAsync(posts, cancellationToken : cancellationToken);

            return(await base.HandleAsync(@event, cancellationToken));
        }
Example #3
0
        public override async Task <GreetingMade> HandleAsync(GreetingMade @event, CancellationToken cancellationToken = default(CancellationToken))
        {
            var posts = new List <Guid>();

            var tx = await _uow.BeginOrGetTransactionAsync(cancellationToken);

            try
            {
                var salutation = new Salutation(@event.Greeting);

                await _uow.Database.InsertAsync <Salutation>(salutation, tx);

                posts.Add(await _postBox.DepositPostAsync(new SalutationReceived(DateTimeOffset.Now), cancellationToken: cancellationToken));

                await tx.CommitAsync(cancellationToken);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Could not save salutation");

                //if it went wrong rollback entity write and Outbox write
                await tx.RollbackAsync(cancellationToken);

                return(await base.HandleAsync(@event, cancellationToken));
            }

            await _postBox.ClearOutboxAsync(posts, cancellationToken : cancellationToken);

            return(await base.HandleAsync(@event, cancellationToken));
        }
        public async override Task <AddGreetingCommand> HandleAsync(AddGreetingCommand command,
                                                                    CancellationToken cancellationToken = default(CancellationToken))
        {
            await _unitOfWork.BeginTransactionAsync(cancellationToken);

            try
            {
                //Save  the new Greeting
                var greeting = new Greeting()
                {
                    GreetingMessage = command.GreetingMessage
                };
                await _dataContext.GreetingsRegister.AddAsync(greeting, cancellationToken);

                //Create an Event for externals
                var newGreetingAddedEvent = new GreetingAsyncEvent()
                {
                    Greeting = command.GreetingMessage
                };
                var eventId = await _commandProcessor.DepositPostAsync(newGreetingAddedEvent, cancellationToken : cancellationToken);

                await _dataContext.SaveChangesAsync(cancellationToken);

                if (command.ThrowError)
                {
                    throw new Exception("something broke error");
                }
                else
                {
                    //Ensure for Testing to Ensure that Contexts are not shared
                    Thread.Sleep(5000);
                }

                await _unitOfWork.CommitAsync(cancellationToken);

                //In Case there is no outbox Sweeper
                await _commandProcessor.ClearOutboxAsync(new[] { eventId }, cancellationToken : cancellationToken);

                Console.WriteLine($"Message {command.GreetingMessage} Saved.");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);

                await _unitOfWork.RollbackAsync(cancellationToken);

                Console.WriteLine($"Message {command.GreetingMessage} not Saved.");
            }


            return(await base.HandleAsync(command));
        }
        public override async Task <AddGreeting> HandleAsync(AddGreeting addGreeting, CancellationToken cancellationToken = default(CancellationToken))
        {
            var posts = new List <Guid>();

            //We span a Db outside of EF's control, so start an explicit transactional scope
            var tx = await _uow.Database.BeginTransactionAsync(cancellationToken);

            try
            {
                var person = await _uow.People
                             .Where(p => p.Name == addGreeting.Name)
                             .SingleAsync(cancellationToken);

                var greeting = new Greeting(addGreeting.Greeting);

                person.AddGreeting(greeting);

                //Now write the message we want to send to the Db in the same transaction.
                posts.Add(await _postBox.DepositPostAsync(new GreetingMade(greeting.Greet()), cancellationToken: cancellationToken));

                //write the changed entity to the Db
                await _uow.SaveChangesAsync(cancellationToken);

                //write new person and the associated message to the Db
                await tx.CommitAsync(cancellationToken);
            }
            catch (Exception)
            {
                //it went wrong, rollback the entity change and the downstream message
                await tx.RollbackAsync(cancellationToken);

                return(await base.HandleAsync(addGreeting, cancellationToken));
            }

            //Send this message via a transport. We need the ids to send just the messages here, not all outstanding ones.
            //Alternatively, you can let the Sweeper do this, but at the cost of increased latency
            await _postBox.ClearOutboxAsync(posts, cancellationToken : cancellationToken);

            return(await base.HandleAsync(addGreeting, cancellationToken));
        }
Example #6
0
        public async Task <IActionResult> SaveAndRollbackMessage()
        {
            var transaction = await _context.Database.BeginTransactionAsync();

            // try
            // {
            var greetingAsync = new GreetingAsyncEvent("Hello from the web - 1");
            var greeting      = new GreetingEvent("Hello from the web - 1");

            _context.Greetings.Add(greeting);
            _context.GreetingsAsync.Add(greetingAsync);

            await _context.SaveChangesAsync();

            _commandProcessor.Post(greeting);
            await _commandProcessor.PostAsync(greetingAsync);

            //throw new Exception("Something went wrong");
            // }
            // catch (Exception e)
            // {
            await transaction.RollbackAsync();

            // }

            var greetingAsync2 = new GreetingAsyncEvent("Hello from the web - 2");
            var greeting2      = new GreetingEvent("Hello from the web - 2");

            _context.Greetings.Add(greeting2);
            _context.GreetingsAsync.Add(greetingAsync2);

            _commandProcessor.DepositPost(greeting2);

            await _context.SaveChangesAsync();

            await _commandProcessor.DepositPostAsync(greetingAsync2);

            return(View("Index"));
        }
Example #7
0
        public override async Task<AddGreeting> HandleAsync(AddGreeting addGreeting, CancellationToken cancellationToken = default(CancellationToken))
        {
            var posts = new List<Guid>();
            
            //We use the unit of work to grab connection and transaction, because Outbox needs
            //to share them 'behind the scenes'
            
            var tx = await _uow.BeginOrGetTransactionAsync(cancellationToken);
            try
            {
                var searchbyName = Predicates.Field<Person>(p => p.Name, Operator.Eq, addGreeting.Name);
                var people = await _uow.Database.GetListAsync<Person>(searchbyName, transaction: tx);
                var person = people.Single();
                
                var greeting = new Greeting(addGreeting.Greeting, person);
                
                //Now write the message we want to send to the Db in the same transaction.
                posts.Add(await _postBox.DepositPostAsync(new GreetingMade(greeting.Greet()), cancellationToken: cancellationToken));
                
                //write the added child entity to the Db
                await _uow.Database.InsertAsync<Greeting>(greeting, tx);

                //commit both new greeting and outgoing message
                await tx.CommitAsync(cancellationToken);
            }
            catch (Exception e)
            {   
                _logger.LogError(e, "Exception thrown handling Add Greeting request");
                //it went wrong, rollback the entity change and the downstream message
                await tx.RollbackAsync(cancellationToken);
                return await base.HandleAsync(addGreeting, cancellationToken);
            }

            //Send this message via a transport. We need the ids to send just the messages here, not all outstanding ones.
            //Alternatively, you can let the Sweeper do this, but at the cost of increased latency
            await _postBox.ClearOutboxAsync(posts, cancellationToken:cancellationToken);

            return await base.HandleAsync(addGreeting, cancellationToken);
        }
Example #8
0
 public async Task <Guid> DepositPostAsync <T>(T request, bool continueOnCapturedContext = false, CancellationToken cancellationToken = default)
     where T : class, IRequest
 {
     return(await _commandProcessor.DepositPostAsync(request, continueOnCapturedContext, cancellationToken));
 }
Example #9
0
        public override async Task <UpdateExistingAccountCommand> HandleAsync(UpdateExistingAccountCommand command, CancellationToken cancellationToken = new CancellationToken())
        {
            Guid eventId;

            using (var uow = new AccountContext(_options))
            {
                using (var trans = uow.Database.BeginTransaction())
                {
                    var accountRepositoryAsync = new AccountRepositoryAsync(new EFUnitOfWork(uow));

                    AggregateLock aggregateLock = null;
                    try
                    {
                        aggregateLock = await accountRepositoryAsync.LockAsync(command.AccountId.ToString(), command.LockBy,
                                                                               cancellationToken);

                        var account = await accountRepositoryAsync.GetAsync(command.AccountId);

                        account.Name           = new Name(account, command.Name.FirstName, command.Name.LastName);
                        account.ContactDetails = new ContactDetails(account, command.ContactDetails.Email, command.ContactDetails.TelephoneNumber);
                        account.CardDetails    = new CardDetails(account, command.CardDetails.CardNumber, command.CardDetails.CardSecurityCode);
                        account.Addresses      = command.Addresses;

                        await accountRepositoryAsync.UpdateAsync(account, aggregateLock, cancellationToken);

                        eventId = await _commandProcessor.DepositPostAsync(new AccountEvent
                        {
                            Id        = Guid.NewGuid(),
                            AccountId = account.AccountId.ToString(),
                            Addresses = account.Addresses.Select(
                                addr => new AddressEvent
                            {
                                AddressType       = addr.AddressType.ToString(),
                                FistLineOfAddress = addr.FistLineOfAddress,
                                State             = addr.State,
                                ZipCode           = addr.ZipCode
                            }).ToList(),
                            Name = new NameEvent {
                                FirstName = account.Name.FirstName, LastName = account.Name.LastName
                            },
                            CardDetails = new CardDetailsEvent
                            {
                                CardNumber       = account.CardDetails.CardNumber,
                                CardSecurityCode = account.CardDetails.CardSecurityCode
                            },
                            ContactDetails = new ContactDetailsEvent
                            {
                                Email           = account.ContactDetails.Email,
                                TelephoneNumber = account.ContactDetails.TelephoneNumber
                            }
                        }, false, cancellationToken);

                        trans.Commit();
                    }
                    finally
                    {
                        if (aggregateLock != null)
                        {
                            await aggregateLock.ReleaseAsync(cancellationToken);
                        }
                    }
                }
            }

            await _commandProcessor.ClearOutboxAsync(new [] { eventId });

            return(await base.HandleAsync(command, cancellationToken));
        }