Exemplo n.º 1
0
 private Product MapToContract(ProductTableEntity productTableEntity)
 {
     return(new Product
     {
         Id = productTableEntity.Id,
         Name = productTableEntity.Name,
         Price = productTableEntity.Price,
     });
 }
Exemplo n.º 2
0
        /// <summary>
        ///     Event handler that listens for PrdouctChanged Events from the catalog service
        ///     and synchronizes the Catalog Read Table in BasketEntity accordingly.
        ///     Handles both productEntity inserts and updates.
        /// </summary>
        /// <param name="productEntity">ProductEntity Information</param>
        /// <param name="correlationId">Tracks request - can be any value</param>
        /// <returns></returns>
        public async Task ProductChanged(ProductEntity productEntity, string correlationId)
        {
            if (productEntity == null)
            {
                _logger.LogWarning($"Missing productEntity information for synchronization event in BasketEntity");
                throw new Exception($"Missing productEntity information for synchronization event in BasketEntity");
            }

            // Transform to ProductTableEntity objects
            var productTableEntity = new ProductTableEntity
            {
                PartitionKey = ProductPartitionKey,
                RowKey       = productEntity.Id.ToString(),
                Title        = productEntity.Title,
                ArtistName   = productEntity.ArtistName,
                GenreName    = productEntity.GenreName,
                Price        = productEntity.Price.ToString(),
                //Upc = productEntity.Upc
            };

            try
            {
                // Determine if record already exists
                var currentReadTableItems =
                    await _productRepository.GetItem(ProductPartitionKey,
                                                     productTableEntity.RowKey, correlationId);

                if (currentReadTableItems == null)
                {
                    // Insert resource
                    await _productRepository.Insert(productTableEntity, correlationId);

                    _logger.LogInformation(
                        $"Inserting ProductEntity {productEntity.Id}, {productTableEntity.Title} into Catalog ReadModel for Request {correlationId}");
                }
                else
                {
                    // Update resource
                    await _productRepository.Update(productTableEntity, correlationId);

                    _logger.LogInformation(
                        $"Updating ProductEntity {productEntity.Id}, {productTableEntity.Title} to Catalog ReadModel  for Request {correlationId}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(new EventId(ex.HResult),
                                 ex,
                                 "Exception throw in ProductChanged() in BasketEntity : {message}", ex.Message);

                throw new Exception($"Error in ProductChanged() in BasketEntity : {ex.Message}");
            }

            await Task.CompletedTask;
        }
Exemplo n.º 3
0
        /// <summary>
        ///     Add single line item to shopping basket
        /// </summary>
        /// <param name="productId">Id of productEntity to add</param>
        /// <param name="correlationToken">Tracks request - can be any value</param>
        /// <param name="basketId">Id of shopping basket</param>
        /// <returns>BasketItemEntity</returns>
        public async Task <BasketEntity> AddItemToBasket(int productId, string correlationToken,
                                                         string basketId)
        {
            //* Materialized View Pattern
            //* Fetch product entity data from a read-only store contained in shopping basket service.
            //* ProductEntity ID is row key in underlying Azure table.
            //* Returns a ProductTableEntity class
            var productTableEntity = await _productRepository.GetItem(ProductPartitionKey, productId.ToString(), correlationToken);

            // Fallback logic
            if (productTableEntity == null)
            {
                // Fallback:
                // If product not available from local read store, fetch it from catalog service by
                // making direct HTTP call to Catalog Service.
                var product = await _restClient.GetAsync <ProductEntity>(ServiceEnum.Catalog, $"api/Catalog/Music/{productId}", correlationToken);

                if (product == null)
                {
                    throw new Exception(
                              $"Cannot add item to shopping basket: ProductEntity #{productId} does not exist for Request {correlationToken}.  Have you created the ProductEntity Read Model for the Shopping BasketEntity microservice?");
                }

                // Transform product into an entity class for table storage
                productTableEntity = new ProductTableEntity
                {
                    // parition key is constant
                    PartitionKey = ProductPartitionKey,
                    // row key is productId
                    RowKey = product.Data.Id.ToString(),

                    Title      = product.Data.Title,
                    Id         = product.Data.Id,
                    GenreName  = product.Data.GenreName,
                    ArtistName = product.Data.ArtistName,
                    Price      = product.Data.Price.ToString()
                };

                // Add product entity tolocal read store, implementing a cache-aside pattern
                await _productRepository.Insert(productTableEntity, correlationToken);

                _logger.LogInformation(
                    $"Added productEntity information for item {productId} for Request {correlationToken} to the read model.");
            }

            BasketEntity basket = null;

            // Does basketID exist?
            if (basketId == "-1")
            {
                basketId = SnowflakeIdGenerator.GenerateId(SnowflakeEnum.Basket);
            }
            else
            {
                basket = await _distributedCacheRepository.GetBasketAsync(basketId, correlationToken, _telemetryClient);
            }

            // Get basket from cache
            if (basket == null)
            {
                // BasketEntity is null, add new single item to it
                basket = new BasketEntity
                {
                    BuyerId          = "2",
                    BasketId         = basketId,
                    CorrelationToken = correlationToken,
                    Items            =
                    {
                        new BasketItemEntity
                        {
                            CorrelationToken = correlationToken,
                            //DateCreated = DateTime.Now,
                            Title     = productTableEntity.Title,
                            UnitPrice = productTableEntity.Price.ToString(),
                            Artist    = productTableEntity.ArtistName,
                            Genre     = productTableEntity.GenreName,
                            Quantity  = 1,
                            ProductId = productId,
                        }
                    }
                };

                basket = await _distributedCacheRepository.UpdateBasketAsync(basket, correlationToken, _telemetryClient);

                _logger.LogInformation($"Created new shopping basket {basketId} and added productEntity {productTableEntity.Title} for Request {correlationToken} ");
            }
            else
            {
                // BasketEntity is not null
                // Determine if the same productEntity has already been added to the basket
                var itemInBasket = basket.Items.FirstOrDefault(x => x.ProductId == Int32.Parse(productTableEntity.RowKey));

                if (itemInBasket == null)
                {
                    // ProductEntity does not exist in basket, add it
                    basket.Items.Add(new BasketItemEntity()
                    {
                        CorrelationToken = correlationToken,
                        //DateCreated = DateTime.Now,
                        Title     = productTableEntity.Title,
                        UnitPrice = productTableEntity.Price.ToString(),
                        Artist    = productTableEntity.ArtistName,
                        Genre     = productTableEntity.GenreName,
                        Quantity  = 1,
                        ProductId = Int32.Parse(productTableEntity.RowKey)
                    });

                    _logger.LogInformation($"Added productEntity Id {productId} to shopping basket {basketId} for request {correlationToken}");
                }
                else
                {
                    // Idempotency write-check
                    // Ensure that update with same correlation token does not already exist.
                    // This could happen if we've already committed the write, but have gotten caught-up in retry logic.
                    if (itemInBasket.CorrelationToken != null && itemInBasket.CorrelationToken == correlationToken)
                    {
                        _logger.LogWarning($"ProductEntity Id {productId} already added to shopping basket {basketId} for Request {correlationToken}");
                        return(basket);
                    }

                    // ProductEntity already exists in basket. Increment its count.
                    basket.Items.FirstOrDefault(x => x.ProductId == Int32.Parse(productTableEntity.RowKey)).Quantity++;

                    _logger.LogInformation($"Added productEntity Id {productId} to existing shopping basket {basketId} for request {correlationToken}");
                }

                basket = await _distributedCacheRepository.UpdateBasketAsync(basket, correlationToken, _telemetryClient);
            }

            return(basket);
        }