From aae799f19ad577527bce3520471ccf3b44ec621e Mon Sep 17 00:00:00 2001 From: deibudei Date: Wed, 6 May 2026 00:26:02 +0800 Subject: [PATCH] =?UTF-8?q?fix(repair):=20=E4=BF=AE=E5=A4=8D=20InventorySe?= =?UTF-8?q?rvice.deduct=20=E7=9A=84=E5=B9=B6=E5=8F=91=E7=AB=9E=E6=80=81?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- target-service/files/welcome.txt | 1 + .../repository/InventoryRepository.java | 22 +++++++++++++++++++ .../service/InventoryService.java | 15 ++----------- 3 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 target-service/files/welcome.txt diff --git a/target-service/files/welcome.txt b/target-service/files/welcome.txt new file mode 100644 index 0000000..13d6eec --- /dev/null +++ b/target-service/files/welcome.txt @@ -0,0 +1 @@ +hello from storage \ No newline at end of file diff --git a/target-service/src/main/java/com/example/targetservice/repository/InventoryRepository.java b/target-service/src/main/java/com/example/targetservice/repository/InventoryRepository.java index adc83df..7c00b00 100644 --- a/target-service/src/main/java/com/example/targetservice/repository/InventoryRepository.java +++ b/target-service/src/main/java/com/example/targetservice/repository/InventoryRepository.java @@ -32,4 +32,26 @@ public InventoryItem save(InventoryItem item) { public int stock(String sku) { return findBySku(sku).stock(); } + + /** + * Atomically deducts stock for a given SKU. + * Uses ConcurrentHashMap.compute to ensure read-check-write atomicity. + * @throws IllegalArgumentException if SKU not found or insufficient stock + */ + public InventoryItem deductStock(String sku, int quantity) { + if (quantity <= 0) { + throw new IllegalArgumentException("quantity must be positive, but got: " + quantity); + } + return store.compute(sku, (key, item) -> { + if (item == null) { + throw new IllegalArgumentException("SKU not found: " + sku); + } + if (item.stock() < quantity) { + throw new IllegalArgumentException( + "insufficient stock for " + sku + ": have " + item.stock() + ", need " + quantity); + } + return new InventoryItem(item.sku(), item.name(), + item.stock() - quantity, item.reserved() + quantity); + }); + } } diff --git a/target-service/src/main/java/com/example/targetservice/service/InventoryService.java b/target-service/src/main/java/com/example/targetservice/service/InventoryService.java index d20a46c..bbe6caf 100644 --- a/target-service/src/main/java/com/example/targetservice/service/InventoryService.java +++ b/target-service/src/main/java/com/example/targetservice/service/InventoryService.java @@ -14,21 +14,10 @@ public InventoryService(InventoryRepository repository) { } /** - * Deducts stock for a given SKU. - * BUG: No synchronization — concurrent calls can over-sell inventory. + * Deducts stock for a given SKU using atomic operation. */ public InventoryItem deduct(String sku, int quantity) { - if (quantity <= 0) { - throw new IllegalArgumentException("quantity must be positive, but got: " + quantity); - } - InventoryItem item = repository.findBySku(sku); - if (item.stock() < quantity) { - throw new IllegalArgumentException( - "insufficient stock for " + sku + ": have " + item.stock() + ", need " + quantity); - } - InventoryItem updated = new InventoryItem(item.sku(), item.name(), - item.stock() - quantity, item.reserved() + quantity); - return repository.save(updated); + return repository.deductStock(sku, quantity); } public InventoryItem getStock(String sku) {