Question

I work on wholesale system domain. When some products are delivered, domain NewProductsDeliveredEvent is triggered. Event contains set of ProductDelivery value objects containing product code and quantity. Something like below:

class NewProductsDeliveredEvent {
  Set<ProductDelivery> productDeliveries;
}

class ProductDelivery { 
  ProductCode productCode;
  Quantity quantity
}

So far so good. Now, when component responsible for inventory updates receives this type of event. It must update products table with the current quantity of products available. So I have something like that:

class NewProudctsDeliveredHandler {
  ProductRepository productRepo;  

  handle(NewProductDeliveryEvent event) {
    for (ProductDelivery delivery : event.getProductDeliveries()) {
      Product product = productRepo.getByCode(delivery.getProductCode())
      product.updateQuantity(delivery.getQuantity());
    }
  }
}

It's easy to spot that such logic generates a lot of DB roundtrips and I'm thinking about some solution to alleviate the pain. One idea might be to use Specification pattern and build OR specification for product codes. However, in my application product code is a business identifier, so this solution smells a little bit (maybe I'm just exaggerating).

Is there any better way to handle it? Any ideas greatly appreciated.

Was it helpful?

Solution

If you'll allow a slight digression, but are you sure that bulk update is a good idea in your case?

Product is an aggregate of high contetion if it manages inventory. Just imagine that maybe hundreds of people are placing orders for the same product at same time on Amazon.com, whereas few people will modify your order at same time.

Take an example:

   Event1:  A-5, B-1
   Event2:  C-1, D-2
   Event3:  A-2, D-3

Event1 conflicts with Event3, Event2 conflicts with Event3

The more product you update in one transaction, the greater chance of a concurrency failure if your products are selling well.

Iterate one product per transaction is even worse, making the event harder to retry.

handle(NewProductDeliveryEvent event) {
    for (ProductDelivery delivery : event.getProductDeliveries()) {
        updateProductTransactionally(); 
        // How to retry the whole event 
        // when the second one failed and the first one committed?
    }
}

Maybe splitting the event to multiple sub events which triggers only one product update is more appropiate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top