public async Task HandleAsync(AddReservationsCommand command, CancellationToken cancellationToken) { using (var context = dbContextFactory.CreateDbContext()) { var productIds = command.Items.Select(i => i.ProductId).ToList(); var productLookup = await GetProductLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false); requestValidator.ValidateAndThrow(command, productLookup); // This is for idempotence. We check only the TransactionId because we assume that if one item in a transaction is reserved then so are the others. var alreadyReserved = await context.ProductReservations.AnyAsync(r => r.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false); if (alreadyReserved) { return; } foreach (var addedReservation in command.Items) { context.ProductReservations.Add(new ProductReservation { ProductId = addedReservation.ProductId, Quantity = addedReservation.Quantity, TransactionId = command.TransactionId }); } await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } }
public async Task HandleAsync(RemoveStocksCommand command, CancellationToken cancellationToken) { using (var context = dbContextFactory.CreateDbContext()) { var productIds = command.Items.Select(i => i.ProductId).ToList(); var productLookup = await GetProductLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false); var availableCountLookup = await GetAvailabileCountLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false); requestValidator.ValidateAndThrow(command, productLookup, availableCountLookup); // This is for idempotence. We check only the TransactionId because we assume that if stocks for one product in a transaction is removed then so are the others. var stocksAlreadyRemoved = await context.ProductStockRemovedEvents.AnyAsync(evt => evt.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false); if (stocksAlreadyRemoved) { return; } foreach (var removedStock in command.Items) { context.ProductStockRemovedEvents.Add(new ProductStockRemovedEvent { ProductId = removedStock.ProductId, Quantity = removedStock.Quantity, TransactionId = command.TransactionId }); } await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } }
public async Task HandleAsync(TakeoutItemsCommand command, CancellationToken cancellationToken) { using (var context = dbContextFactory.CreateDbContext()) { var productIds = command.Items.Select(i => i.ProductId).ToList(); var productLookup = await GetProductLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false); var reservationLookup = await GetReservationLookupAsync(context, command.TransactionId, cancellationToken).ConfigureAwait(false); var availableCountLookup = await GetAvailabileCountLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false); requestValidator.ValidateAndThrow(command, productLookup, reservationLookup, availableCountLookup); // This is for idempotence. We check only the TransactionId because we assume that if one item in a transaction is taken out then so are the others. var itemsAlreadyTakenOut = await context.ProductTakenOutEvents.AnyAsync(evt => evt.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false); if (itemsAlreadyTakenOut) { return; } foreach (var takenOutItem in command.Items) { context.ProductTakenOutEvents.Add(new ProductTakenOutEvent { ProductId = takenOutItem.ProductId, Quantity = takenOutItem.Quantity, TransactionId = command.TransactionId }); } await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } }
public async Task <GetProductByIdResponse> HandleAsync(GetProductByIdRequest request, CancellationToken cancellationToken) { using (var context = dbContextFactory.CreateDbContext()) { var product = await context.Products.FindAsync(new[] { request.ProductId }, cancellationToken).ConfigureAwait(false); if (product == null) { return(null); } return(new GetProductByIdResponse { Name = product.Name, ProductId = product.Id, PointsCost = product.PointsCost }); } }
public async Task HandleAsync(CancelReservationsCommand command, CancellationToken cancellationToken) { using (var context = dbContextFactory.CreateDbContext()) { requestValidator.ValidateAndThrow(command); var productReservations = await context .ProductReservations .Where(evt => evt.TransactionId == command.TransactionId) .ToListAsync(cancellationToken) .ConfigureAwait(false); if (productReservations.Count == 0) { return; } context.ProductReservations.RemoveRange(productReservations); await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } }
public async Task HandleAsync(BringbackItemsCommand command, CancellationToken cancellationToken) { using (var context = dbContextFactory.CreateDbContext()) { requestValidator.ValidateAndThrow(command); // This is for idempotence. We check only the TransactionId because we assume that if one item in a transaction is brought back then so are the others. var itemsAlreadyBroughtBack = await context.ProductBroughtBackEvents.AnyAsync(evt => evt.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false); if (itemsAlreadyBroughtBack) { return; } var correspondingTakeoutEvents = await context .ProductTakenOutEvents .AsNoTracking() .Where(evt => evt.TransactionId == command.TransactionId) .ToListAsync(cancellationToken) .ConfigureAwait(false); if (correspondingTakeoutEvents.Count == 0) { return; } foreach (var takeoutEvent in correspondingTakeoutEvents) { context.ProductBroughtBackEvents.Add(new ProductBroughtBackEvent { ProductId = takeoutEvent.ProductId, Quantity = takeoutEvent.Quantity, TransactionId = command.TransactionId }); } await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } }
public async Task <CreateProductResponse> HandleAsync(CreateProductCommand command, CancellationToken cancellationToken) { requestValidator.ValidateAndThrow(command); using (var context = dbContextFactory.CreateDbContext()) { var product = new Product { Name = command.Name, PointsCost = command.PointsCost }; context.Products.Add(product); await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return(new CreateProductResponse { PointsCost = product.PointsCost, ProductId = product.Id, Name = product.Name }); } }