예제 #1
0
        protected override Task <RequestStatus> HandleCommand(CancelBidCommand request, CancellationToken cancellationToken)
        {
            var auction = FindAuction(request);
            var bid     = FindBid(request, auction);
            var user    = FindUser(request);

            auction.CancelBid(user, bid);


            var transactionOpt = new TransactionOptions()
            {
                IsolationLevel = IsolationLevel.Serializable,
                Timeout        = TimeSpan.FromSeconds(10)
            };

            using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOpt))
            {
                _auctionRepository.UpdateAuction(auction);
                _userRepository.UpdateUser(user);
                scope.Complete();
            }


            _eventBusService.Publish(auction.PendingEvents.Concat(user.PendingEvents), request.CommandContext.CorrelationId, request);
            auction.MarkPendingEventsAsHandled();
            user.MarkPendingEventsAsHandled();

            return(Task.FromResult(RequestStatus.CreateFromCommandContext(request.CommandContext, Status.COMPLETED)));
        }
        public void Queue_Processing_CorruptedEvent()
        {
            // Enqueue events for further handling
            bus.Subscribe(testService.Enque <TestEvent>());

            // except test to throw Exception event
            Exception exception = null;

            bus.Subscribe <Exception>(e =>
                                      exception = e);

            int counter          = 0;
            int backofIntervalMs = 50;
            // Subscribe handler which waits 50 ms
            Delegate <TestEvent> handler = (e) => { counter++; throw new NotImplementedException(); };

            bus.Subscribe(handler.WhenQueued().RetryQueued(3,
                                                           Backoff.Fixed(TimeSpan.FromMilliseconds(backofIntervalMs))
                                                           ));

            bus.Publish(new TestEvent(), this);

            // There is event to handle
            Assert.AreEqual(1, repository.Queue.Where(e => e.DeclaringEventType == typeof(TestEvent).AssemblyQualifiedName).Count());

            testService.ProcessEvents();

            Assert.AreEqual(0, repository.Queue.Where(e => e.DeclaringEventType == typeof(TestEvent).ToString()).Count());
            Assert.IsNotNull(exception);
            Assert.IsInstanceOfType(exception, typeof(FormatException));
        }
예제 #3
0
        protected override Task <RequestStatus> HandleCommand(SignUpCommand request, CancellationToken cancellationToken)
        {
            var existing = _userAuthenticationDataRepository.FindUserAuth(request.Username);

            if (existing != null)
            {
                throw new UsernameConflictException($"User {request.Username} already exists");
            }

            var user = new User();

            user.Register(request.Username);

            var response = RequestStatus.CreateFromCommandContext(request.CommandContext, Status.COMPLETED);
            var userAuth = new UserAuthenticationData()
            {
                Password = request.Password,
                UserId   = user.UserIdentity.UserId,
                UserName = user.UserIdentity.UserName,
                Email    = request.Email
            };

            _userAuthenticationDataRepository.AddUserAuth(userAuth);
            _userRepository.AddUser(user);
            _eventBusService.Publish(user.PendingEvents, response.CorrelationId, request);
            user.MarkPendingEventsAsHandled();

            return(Task.FromResult(response));
        }
        protected override Task <RequestStatus> HandleCommand(UpdateAuctionCommand request, CancellationToken cancellationToken)
        {
            var auction = GetAuction(request);

            if (!auction.Owner.UserId.Equals(request.SignedInUser.UserId))
            {
                throw new UnauthorizedAccessException($"User is not owner of an auction {auction.AggregateId}");
            }


            auction.UpdateTags(request.Tags.Select(s => new Tag(s)).ToArray());
            auction.UpdateName(request.Name);
            auction.UpdateBuyNowPrice(request.BuyNowPrice);
            auction.UpdateDescription(request.Description);
            if (request.EndDate != null)
            {
                auction.UpdateEndDate(request.EndDate);
            }
            var newCategory = _categoryBuilder.FromCategoryNamesList(request.Category);

            auction.UpdateCategory(newCategory);

            var response = RequestStatus.CreateFromCommandContext(request.CommandContext, Status.PENDING);

            _auctionRepository.UpdateAuction(auction);
            _eventBusService.Publish(auction.PendingEvents, response.CorrelationId, request);

            return(Task.FromResult(response));
        }
예제 #5
0
        protected override Task <RequestStatus> HandleCommand(BuyNowCommand request, CancellationToken cancellationToken)
        {
            var user = _userRepository.FindUser(request.SignedInUser);

            if (user == null)
            {
                _logger.LogError("BuyNowCommandHandler cannot find user {@user}", request.SignedInUser);
                throw new CommandException($"Cannot find user: {user.UserIdentity}");
            }

            var auction = _auctionRepository.FindAuction(request.AuctionId);

            if (auction == null)
            {
                throw new CommandException($"Invalid auction id: {request.AuctionId}");
            }

            var buyNowService = new BuyNowService(_userRepository);

            var generatedEvents = buyNowService.BuyNow(auction, user);

            generatedEvents.AddRange(auction.PendingEvents);
            generatedEvents.AddRange(user.PendingEvents);

            _auctionRepository.UpdateAuction(auction);
            _userRepository.UpdateUser(user);

            _eventBusService.Publish(generatedEvents, request.CommandContext.CorrelationId, request);

            return(Task.FromResult(RequestStatus.CreateFromCommandContext(request.CommandContext, Status.PENDING)));
        }
예제 #6
0
 protected virtual void SubscribeForRequeueStuckEvents(EventBusService eventBus)
 {
     eventBus.Subscribe(Enque <RequeueStuckEvents>(TimeSpan.FromSeconds(40)));
     eventBus.Subscribe(this.WhenQueued());
     // enqueue a first event
     eventBus.Publish(new RequeueStuckEvents(), this);
 }
예제 #7
0
        private void ReplaceAuctionImage(UserReplaceAuctionImageCommand request, CancellationToken cancellationToken, CorrelationId correlationId)
        {
            var auction = _auctionRepository.FindAuction(request.AuctionId);

            if (auction == null)
            {
                throw new CommandException($"Cannot find auction {request.AuctionId}");
            }

            var file = File.ReadAllBytes(request.TempPath);

            File.Delete(request.TempPath);

            var img = new AuctionImageRepresentation(new AuctionImageMetadata(request.Extension), file);

            var newImg = _auctionImageService.AddAuctionImage(img);

            auction.ReplaceImage(newImg, request.ImgNum);

            _auctionRepository.UpdateAuction(auction);
            try
            {
                _eventBusService.Publish(auction.PendingEvents, correlationId, request);
            }
            catch (Exception)
            {
                _auctionImageService.RemoveAuctionImage(newImg);
                throw;
            }
        }
        protected override Task <RequestStatus> HandleCommand(BuyCreditsCommand request,
                                                              CancellationToken cancellationToken)
        {
            //DEMO
            if (request.Ammount != 15 && request.Ammount != 40 && request.Ammount != 100)
            {
                throw new InvalidCommandException($"Invalid amount value: {request.Ammount}");
            }

            var user = _userRepository.FindUser(request.SignedInUser);

            if (user == null)
            {
                throw new CommandException("Cannot find user");
            }

            user.AddCredits(request.Ammount);
            _userRepository.UpdateUser(user);
            _eventBusService.Publish(user.PendingEvents, request.CommandContext.CorrelationId, request);
            user.MarkPendingEventsAsHandled();

            var status = RequestStatus.CreateFromCommandContext(request.CommandContext, Status.PENDING);

            return(Task.FromResult(status));
        }
예제 #9
0
 public virtual void Handle(RequeueStuckEvents e)
 {
     try
     {
         _repository.RequeueOldEvents(RequeueTimeLimit);
     }
     finally
     {
         _eventBusService.Publish(e.Clone(), this);
     }
 }
예제 #10
0
 public void Callback(IAsyncResult result)
 {
     try
     {
         _handler.EndInvoke(result);
     }
     catch (Exception ex)
     {
         _eventBusService.Publish <Exception>(ex, this);
     }
 }
예제 #11
0
        /// <summary>
        /// Thos method used to publish event and handle exception, if happened
        /// </summary>
        /// <param name="item"></param>
        protected virtual void onProcessQueueItem(IQueueItem item)
        {
            MethodInfo genericMethod;
            object     typedEvent;
            object     sender;

            // Any exception within following try/catch block is final
            // report exception for handing and remove event from queue as failed
            try
            {
                genericMethod = GetPublishMethodInfo(item.DeclaringEventType);
                typedEvent    = BuildGenericQueueEvent(item);
                sender        = BuildSender(item.DeclaringEventType);
            }
            catch (Exception ex)
            {
                onEventFailed(item, ex);
                _eventBusService.Publish <Exception>(ex, this);
                return;
            }

            // Event handling here
            try
            {
                genericMethod.Invoke(_eventBusService, new[] { typedEvent, sender });
                onEventHandled(item);
            }
            // Exceptions from actual delegate are wrapped into TargetInvocationException by MethodBase.Invoke()
            catch (TargetInvocationException ex)
            {
                RetryNeededException retry = ex.InnerException as RetryNeededException;
                if (retry != null)
                {
                    onEventRetried(item, retry);
                }
                else
                {
                    onEventFailed(item, ex.InnerException);
                }
            }
        }
        protected override Task <RequestStatus> HandleCommand(EndAuctionCommand request, CancellationToken cancellationToken)
        {
            var auction = _auctionRepository.FindAuction(request.AuctionId);

            auction.EndAuction();
            _eventBusService.Publish(auction.PendingEvents, null, request);
            auction.MarkPendingEventsAsHandled();

            var response = RequestStatus.CreateFromCommandContext(request.CommandContext, Status.COMPLETED);

            return(Task.FromResult(response));
        }
예제 #13
0
        private void RemoveAuctionImage(UserRemoveAuctionImageCommand request, CancellationToken cancellationToken, CorrelationId correlationId)
        {
            var auction = _auctionRepository.FindAuction(request.AuctionId);

            if (auction == null)
            {
                throw new CommandException($"Cannot find auction {request.AuctionId}");
            }

            auction.RemoveImage(request.ImgNum);


            _auctionRepository.UpdateAuction(auction);
            _eventBusService.Publish(auction.PendingEvents, correlationId, request);
        }
예제 #14
0
        private void AddImage(UserAddAuctionImageCommand request, CancellationToken cancellationToken, CorrelationId correlationId)
        {
            var auction = _auctionRepository.FindAuction(request.AuctionId);

            if (auction == null)
            {
                throw new CommandException($"Cannot find auction {request.AuctionId}");
            }

            if (!auction.Owner.UserId.Equals(request.SignedInUser.UserId))
            {
                throw new CommandException(
                          $"User {request.SignedInUser.UserId} cannot modify auction ${auction.AggregateId}");
            }

            var file = File.ReadAllBytes(request.TempPath);

            File.Delete(request.TempPath);

            var img = new AuctionImageRepresentation(new AuctionImageMetadata(request.Extension), file);

            var newImg = _auctionImageService.AddAuctionImage(img);

            auction.AddImage(newImg);

            _auctionRepository.UpdateAuction(auction);
            try
            {
                _eventBusService.Publish(auction.PendingEvents, correlationId, request);
            }
            catch (Exception e)
            {
                _logger.LogWarning(e, "Error while trying to publish events");
                _auctionImageService.RemoveAuctionImage(newImg);
                throw;
            }
        }
예제 #15
0
        protected override Task <RequestStatus> HandleCommand(BidCommand request, CancellationToken cancellationToken)
        {
            var auction = _auctionRepository.FindAuction(request.AuctionId);

            if (auction == null)
            {
                throw new CommandException("Invalid auction id");
            }

            var user = _userRepository.FindUser(request.SignedInUser);

            if (user == null)
            {
                throw new CommandException($"Cannot find user {request.SignedInUser.UserName}");
            }

            auction.Raise(user, request.Price);
            var bid = auction.Bids.Last();

            var response = RequestStatus.CreateFromCommandContext(request.CommandContext, Status.PENDING);

            _auctionRepository.UpdateAuction(auction);
            _userRepository.UpdateUser(user);
            var toSend = auction.PendingEvents.Concat(user.PendingEvents);

            _eventBusService.Publish(toSend, response.CorrelationId, request);
            _requestStatusService.TrySendNotificationToAll("AuctionPriceChanged", new Dictionary <string, object>()
            {
                { "winningBid", bid }
            });
            auction.MarkPendingEventsAsHandled();
            _logger.LogDebug("Bid {@bid} submited for an auction {@auction} by {@user}", bid, auction, request.SignedInUser);


            return(Task.FromResult(response));
        }
        public void Queue_ProcessingTimelimit()
        {
            // Enqueue events for further handling
            bus.Subscribe(testService.Enque <TestEvent>());

            // Subscribe handler which waits 50 ms
            bus.Subscribe <QueuedEvent <TestEvent> >((e) => Task.Delay(50).Wait());

            for (int i = 0; i < 10; i++)
            {
                bus.Publish(new TestEvent(), this);
            }

            // expect to handle no more than 5 events
            testService.ProcessingTimeLimit = TimeSpan.FromMilliseconds(249);
            var result = testService.ProcessEvents();

            Console.Write($"Number of items processed: {result.Processed}");
            Assert.IsTrue(4 == result.Processed || 5 == result.Processed);
        }