Repository navigation
feat(example): add the inventory context to ddk-mall - #76
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
Second step of the
ddk-mallreference application: the inventory context. Stock is the hot spot of the order flow. Many orders compete for the same SKU, one order touches several SKUs, and the operations will soon be driven by messages that can arrive more than once.Changes
com.example.mall.inventory, with its own four layers.Stock: on-hand and reserved quantities per SKU. Reserving keeps the goods on hand but not available; they leave the warehouse only when the order is paid.StockReservation: one record per order and SKU. It makes release and deduction repeatable: a second release finds the record already released and changes nothing.InventoryService: reserve for all lines of an order or for none, release, confirm, restock.StockLockport with one implementation: DDK'sAggregateLocks.executeAllwhen Redis is available, in-process locks otherwise.docker-compose.ymlgains Redis, and themysqlprofile is renamedcompose. The default profile still starts without external components.Design decisions:
ArchitectureTestnow has two contexts to check.mvn spring-boot:runfree of external dependencies.StockConcurrencyIntegrationTestruns against real MySQL and Redis: twenty orders reserve one unit each of a SKU with three in stock. Exactly three succeed, seventeen getINSUFFICIENT_STOCK, and the stored reserved quantity is three.背景
ddk-mall参考应用的第二步:库存上下文。库存是下单流程里的热点:很多订单抢同一个 SKU,一个订单又涉及多个 SKU,而且这些操作很快要由可能重复投递的消息来驱动。改动
com.example.mall.inventory,内部同样是四层。Stock:每个 SKU 的在库数量和已预占数量。预占的货还在库里,只是不再可售;订单支付后才真正出库。StockReservation:每个订单每个 SKU 一条预占记录。有了它,释放和扣减可以重复执行:第二次释放时记录已经是已释放状态,什么都不会改。InventoryService:为订单的所有行预占(要么全占,要么都不占)、释放、扣减、补货。StockLock端口及其实现:有 Redis 时用 DDK 的AggregateLocks.executeAll,否则用进程内的锁。docker-compose.yml增加 Redis,mysqlprofile 改名为compose。默认 profile 仍然不依赖外部组件。预占流程见上文伪代码。设计取舍:
ArchitectureTest里的切片规则现在有两个上下文可以检查了。mvn spring-boot:run不需要任何外部依赖。StockConcurrencyIntegrationTest连接真实的 MySQL 和 Redis:20 个订单各预占 1 件只有 3 件库存的 SKU,恰好 3 个成功,17 个得到INSUFFICIENT_STOCK,库里记录的预占数量是 3。