Inventory
The concept of Inventory represents quantity that is available for a particular Sku at a particular Fulfillment Location. In this module, inventory is not reserved until the user actually checks out. Therefore, it is possible that 2 Customers could have an item in their cart for more inventory than is actually available in the system. If both users were to checkout, then the user that checked out first would 'win' and checkout would be successful. For the second user, the blCheckoutWorkflow
would throw an InventoryUnavailableException
and checkout would not succeed.
Optimistic Row-locking
In order to deal with high-contention scenarios, optimistic row-locking takes place when actually decrementing inventory. Under the covers, right before decrementing inventory the system executes a readForUpdate
through Hibernate, ignoring all caching. This ensures that the most up-to-date inventory is retrieved and also 'locks' the record so that no other user can update that inventory.
However, even after locking inventory can still be read from the system. The failure in this case would be on an update. When the system attemps to actually update the database record, an exception is thrown if another Customer has the inventory already locked. There is a retry policy in place to deal with this scenario and to 'refresh' the current read inventory. The algorithm goes like this for decrementing inventory:
- Read inventory for update (lock the database record, ignore caching)
- Check to make sure there is enough quantity
- Execute the database 'update' query
- If there is an exception (meaning someone else executed a
readForUpdate
before us), go back to 1.
The default retry policy is to retry this process 5 times. This can be customized by the advanced-inventory.operation.maxretries
system property.
Inventory Service Customizations
Advanced Inventory provides an implementation of the InventoryServiceExtensionHandler. Most customizations will occur via the InventoryLocationResolver or the InventoryReservationStrategy but you can also wholesale replace this component by overriding the blAdvancedInventoryServiceExtensionHandler
bean.
This also means that if you have existing components that are utilizing the framework InventoryService
then those will continue to work. However, we recommend using the AdvancedInventoryService
methods whenever possible.
Quantity Available vs Quantity On Hand
This is not an often-used feature of the advanced inventory module and is not enabled out of the box
Both of these concepts are available in the advanced inventory module but only quantity available is enabled out of the box. Quantity available is used for all eCommerce operations: checking if inventory is available, decrementing inventory, etc. If you are using the advanced inventory module as your entire inventory system, however, then you might also want to use quantity on hand. This concept allows for you to keep track of how much stock you actually have on your shelves which could be different than how much you sell online. You might also have a "brick and morter" store where you need to always keep at least 5 items in stock. Therefore, your "quantity available" might be 15 in this case but the "quantity on hand" might be 20.
Out of the box, the advanced inventory module hides the quantity on hand field as the common case would be to integrate with a different "system of record". If you would like to enable this functionality, override the advanced-inventory.quantityOnHand.management.enabled
system property.