Skip to content

Commit

Permalink
feat: 상품수량 변경 로직 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
non-cpu committed May 16, 2024
1 parent 462d16e commit fbcf914
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
import com.blanc.market.domain.review.entity.Review;
import com.blanc.market.domain.searchHistory.entity.SearchHistory;
import com.blanc.market.global.entity.BaseEntity;
import org.hibernate.annotations.Where;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.LazyGroup;
import org.hibernate.annotations.Where;

import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -45,6 +44,8 @@ public class Product extends BaseEntity {
@OneToMany(mappedBy = "product", fetch = FetchType.LAZY)
private List<SearchHistory> searchHistories;

private int count;

private int likeCount;


Expand Down Expand Up @@ -78,6 +79,10 @@ public void addProductIngredient(ProductIngredient productIngredient) {
productIngredients.add(productIngredient);
}

public void setCount(int count) {
this.count = count;
}

public void setLikeCount(int likeCount) {
this.likeCount = likeCount;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@

import com.blanc.market.domain.product.entity.Category;
import com.blanc.market.domain.product.entity.Product;
import jakarta.persistence.LockModeType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

List<Product> findByNameContaining(String keyword);
Page<Product> findByNameContaining(String keyword, Pageable pageable);
Page<Product> findByCategory(Category category, Pageable pageable);

@Query(value = "select get_lock(:key, 1000)", nativeQuery = true)

@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("select p from Product p where p.id = :id")
Optional<Product> findByIdWithPessimisticLock(Long id);

@Query(value = "select get_lock(:key, 128)", nativeQuery = true)
void getLock(String key);

@Query(value = "select release_lock(:key)", nativeQuery = true)
void releaseLock(String key);


}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import com.blanc.market.domain.product.dto.ProductRequest;
import com.blanc.market.domain.product.dto.ProductResponse;
import com.blanc.market.domain.product.dto.ProductUpdateRequest;
import com.blanc.market.domain.product.entity.Product;
import com.blanc.market.domain.product.mapper.ProductMapper;
import com.blanc.market.domain.product.repository.ProductRepository;
import com.blanc.market.domain.review.dto.ReviewResponse;
Expand Down Expand Up @@ -157,6 +156,12 @@ public void updateProduct(Long productId, ProductUpdateRequest request) {
product.update(request);
}

@Transactional
public void updateProductCount(Long productId, int incrementValue) {
Product product = productRepository.findByIdWithPessimisticLock(productId).orElseThrow();
product.setCount(product.getCount() + incrementValue);
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateLikeCount(Long productId, int incrementValue) {
Product product = productRepository.findById(productId).orElseThrow();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ class ProductServiceTest {

private Product testProduct;

private final int taskCount = 32;

private void executeParallel(int taskCount, Runnable runnable) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(8);
CountDownLatch latch = new CountDownLatch(taskCount);

for (int i = 0; i < taskCount; i++) {
executorService.submit(() -> {
try {
runnable.run();
} finally {
latch.countDown();
}
});
}

latch.await();
}

@BeforeEach
void setUp() {
testProduct = productRepository.save(Product.builder()
Expand Down Expand Up @@ -103,27 +122,26 @@ void getReviewsForProduct() {

@Test
@Transactional(propagation = Propagation.NEVER)
void updateLikeCount() throws InterruptedException {
int initialLikeCount = testProduct.getLikeCount();
void updateCount() throws InterruptedException {
int initialCount = testProduct.getCount();

int threadCount = 32;
ExecutorService executorService = Executors.newFixedThreadPool(8);
CountDownLatch latch = new CountDownLatch(threadCount);
this.executeParallel(this.taskCount,
() -> productService.updateProductCount(testProduct.getId(), 1));

for (int i = 0; i < threadCount; i++) {
executorService.submit(() -> {
try {
namedLockProductFacade.updateLikeCount(testProduct.getId(), 1);
} finally {
latch.countDown();
}
});
}
Product product = productRepository.findById(testProduct.getId()).orElseThrow();
assertEquals(initialCount + this.taskCount, product.getCount());
}

latch.await();
@Test
@Transactional(propagation = Propagation.NEVER)
void updateLikeCount() throws InterruptedException {
int initialLikeCount = testProduct.getLikeCount();

this.executeParallel(this.taskCount,
() -> namedLockProductFacade.updateLikeCount(testProduct.getId(), 1));

Product product = productRepository.findById(testProduct.getId()).orElseThrow();
assertEquals(initialLikeCount + threadCount, product.getLikeCount());
assertEquals(initialLikeCount + this.taskCount, product.getLikeCount());
}

@Test
Expand Down

0 comments on commit fbcf914

Please sign in to comment.