From 4c7c3d334559fdb3516daf4e62306ea8bd52dcb9 Mon Sep 17 00:00:00 2001 From: kimscott Date: Mon, 10 Feb 2020 13:34:44 +0900 Subject: [PATCH] add saga rollback --- .../com/example/template/Application.java | 2 +- .../example/template/ProductController.java | 10 +++++- .../example/template/ProductOutOfStock.java | 36 +++++++++++++++++++ .../com/example/template/ProductService.java | 20 ++++++++--- 4 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/example/template/ProductOutOfStock.java diff --git a/src/main/java/com/example/template/Application.java b/src/main/java/com/example/template/Application.java index 8ddda12..c934510 100644 --- a/src/main/java/com/example/template/Application.java +++ b/src/main/java/com/example/template/Application.java @@ -28,7 +28,7 @@ public class Application { product.setImageUrl("https://github.githubassets.com/images/modules/profile/profile-joined-github.png"); product.setName(p); product.setPrice(i*10000); - product.setStock(i*1000000); + product.setStock(i*10); product.setImageUrl("/goods/img/"+p+".jpg"); // 상품 디테일 추가 - 양방향 관계 diff --git a/src/main/java/com/example/template/ProductController.java b/src/main/java/com/example/template/ProductController.java index dc59543..ed7c630 100644 --- a/src/main/java/com/example/template/ProductController.java +++ b/src/main/java/com/example/template/ProductController.java @@ -1,6 +1,7 @@ package com.example.template; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -48,7 +49,14 @@ public class ProductController { @PatchMapping("/product/{productId}") - @HystrixCommand(fallbackMethod = "certifyFallBack") + @HystrixCommand( + fallbackMethod = "certifyFallBack", + commandProperties = { + @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"), // 기본 타임아웃 + @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"), // 서킷브레이커가 작하게될 에러 퍼센트 + @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"), // 서킷브레이커가 열리기 위한 최소 요청조 (10초간 19번이 실패해도 서킷은 오픈 안됨) + @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000") } // 서킷브래이커가 열렸을때 얼마나 유지할지 + ) ResponseEntity fakeProductPatch(@PathVariable(value = "productId") Long productId, @RequestBody String data) { count++; diff --git a/src/main/java/com/example/template/ProductOutOfStock.java b/src/main/java/com/example/template/ProductOutOfStock.java new file mode 100644 index 0000000..2c486ce --- /dev/null +++ b/src/main/java/com/example/template/ProductOutOfStock.java @@ -0,0 +1,36 @@ +package com.example.template; + +public class ProductOutOfStock extends AbstractEvent { + + private String stateMessage = "재고량 바닥"; + private Long productId; + private Long orderId; + + public ProductOutOfStock(){ + super(); + } + + public String getStateMessage() { + return stateMessage; + } + + public void setStateMessage(String stateMessage) { + this.stateMessage = stateMessage; + } + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long orderId) { + this.orderId = orderId; + } +} diff --git a/src/main/java/com/example/template/ProductService.java b/src/main/java/com/example/template/ProductService.java index 246c20b..8122233 100644 --- a/src/main/java/com/example/template/ProductService.java +++ b/src/main/java/com/example/template/ProductService.java @@ -37,7 +37,17 @@ public class ProductService { Product product = productOptional.get(); product.setStock(product.getStock() - orderPlaced.getQuantity()); - productRepository.save(product); + if( product.getStock() < 0 ){ + System.out.println("productOutOfStock 이벤트 발생"); + ProductOutOfStock productOutOfStock = new ProductOutOfStock(); + productOutOfStock.setProductId(orderPlaced.getProductId()); + productOutOfStock.setOrderId(orderPlaced.getOrderId()); + productOutOfStock.publish(); + + }else{ + productRepository.save(product); + } + } @@ -47,9 +57,11 @@ public class ProductService { if( orderPlaced.getEventType().equals(OrderCancelled.class.getSimpleName())){ Optional productOptional = productRepository.findById(orderPlaced.getProductId()); Product product = productOptional.get(); - product.setStock(product.getStock() + orderPlaced.getQuantity()); - - productRepository.save(product); + // productOutOfStock 상황이 아닐때만 재고량을 늘린다. + if( product.getStock() - orderPlaced.getQuantity() > 0 ){ + product.setStock(product.getStock() + orderPlaced.getQuantity()); + productRepository.save(product); + } } }catch (Exception e){