본문 바로가기

트러블슈팅

Redis Lock 적용 중 Lock은 적용되나 재고 처리가 제대로 되지 않음

제이미터 상으로 에러가 나지 않고 주문은 잘 생성되고, 테스트 코드도 잘 동작하지만 재고 차감이 제대로 이루어지지 않음

→ 테스트는 서비스 메서드만 타고, 주문은 잘 생성되는 거 보면 서비스 메서드를 가기 전에 발생되는 문제

→ 컨트롤러에서 Stock을 찾아준 것이 1차 캐싱되어 서비스 메서드에 있는 findStockById를  실행하지 않고 캐시되어 있는 stock을 그대로 가져옴

→ 컨트롤러에서 Stock찾기를 빼주고 LockName을 productId로 변경

이전 코드

// Controller
@PostMapping("/products/{productId}/orders")
public ResponseEntity<OrderResponseDto> createOrder(@PathVariable Long productId,
                                                    @RequestBody OrderRequestDto orderRequestDto,
                                                    @AuthenticationPrincipal UserDetailsImpl userDetails){
    User user = userDetails.getUser();
    Stock stock = stockService.findStockById(productId);
    OrderResponseDto orderResponseDto = orderService.createOrder(stock.getStockId(), productId, orderRequestDto, user);
    return ResponseEntity.ok(orderResponseDto);
}

// Service
@DistributedLock(key = "#lockName")
public OrderResponseDto createOrder(Long lockName, Long productId, OrderRequestDto orderRequestDto, User user) {
    Product product = productService.findProduct(productId);
    Stock stock = stockService.findStockById(productId);

    if (stock.getProductStock() < orderRequestDto.getQuantity()) {
        throw new IllegalArgumentException(ErrorMessage.NOT_EXIST_STOCK_ERROR_MESSAGE.getErrorMessage());
    }

    Orders order = new Orders(orderRequestDto, product, user, false);
    stock.updateStock(orderRequestDto.getQuantity());
    orderRepository.save(order);

    return new OrderResponseDto(order);
}

변경 코드

// Controller
@PostMapping("/products/{productId}/orders")
public ResponseEntity<OrderResponseDto> createOrder(@PathVariable Long productId,
                                          @RequestBody OrderRequestDto orderRequestDto,
                                          @AuthenticationPrincipal UserDetailsImpl userDetails){
    User user = userDetails.getUser();
    OrderResponseDto orderResponseDto = orderService.createOrder(productId, orderRequestDto, user);
    return ResponseEntity.ok(orderResponseDto);
}

// Service
****@DistributedLock(key = "#productId")
public OrderResponseDto createOrder(Long productId, OrderRequestDto orderRequestDto, User user) {
    Stock stock = stockService.findStockWithProduct(productId);
    Product product = stock.getProduct();

    if (stock.getProductStock() < orderRequestDto.getQuantity()) {
        throw new IllegalArgumentException(ErrorMessage.NOT_EXIST_STOCK_ERROR_MESSAGE.getErrorMessage());
    }

    Orders order = new Orders(orderRequestDto, product, user, false);
    stock.updateStock(orderRequestDto.getQuantity());
    orderRepository.save(order);

    return new OrderResponseDto(order);
}