diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java index f82c964..1a8f895 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java @@ -28,7 +28,7 @@ import static java.time.LocalDate.parse; import static org.springframework.http.HttpStatus.NOT_FOUND; -import static org.springframework.transaction.annotation.Isolation.SERIALIZABLE; +import static org.springframework.transaction.annotation.Isolation.REPEATABLE_READ; import static org.tenten.tentenstomp.domain.trip.dto.response.TripItemMsg.fromTripItemList; import static org.tenten.tentenstomp.global.common.constant.ErrorMsgConstant.NOT_FOUND_TRIP; import static org.tenten.tentenstomp.global.common.enums.Transportation.CAR; @@ -37,7 +37,7 @@ import static org.tenten.tentenstomp.global.util.SequenceUtil.updateSeqNum; @Service -@Transactional(isolation = SERIALIZABLE) +@Transactional(isolation = REPEATABLE_READ) @RequiredArgsConstructor public class TripItemService { private final TripItemRepository tripItemRepository; diff --git a/src/main/java/org/tenten/tentenstomp/global/aspect/RedissonTransaction.java b/src/main/java/org/tenten/tentenstomp/global/aspect/RedissonTransaction.java new file mode 100644 index 0000000..b0ec59f --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/global/aspect/RedissonTransaction.java @@ -0,0 +1,15 @@ +package org.tenten.tentenstomp.global.aspect; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW; + +@Component +public class RedissonTransaction { + @Transactional(propagation = REQUIRES_NEW, timeout = 3) + public Object proceed(final ProceedingJoinPoint joinPoint) throws Throwable { + return joinPoint.proceed(); + } +} diff --git a/src/main/java/org/tenten/tentenstomp/global/aspect/UtilAspect.java b/src/main/java/org/tenten/tentenstomp/global/aspect/UtilAspect.java index c3c9c03..9dd83c4 100644 --- a/src/main/java/org/tenten/tentenstomp/global/aspect/UtilAspect.java +++ b/src/main/java/org/tenten/tentenstomp/global/aspect/UtilAspect.java @@ -10,7 +10,6 @@ import org.redisson.api.RedissonClient; import org.springframework.stereotype.Component; import org.tenten.tentenstomp.global.common.annotation.WithRedissonLock; -import org.tenten.tentenstomp.global.lock.RedissonTransactionFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -24,7 +23,8 @@ @RequiredArgsConstructor public class UtilAspect { private final RedissonClient redissonClient; - private final RedissonTransactionFactory transactionFactory; + private final RedissonTransaction redissonTransaction; + @Around("@annotation(org.tenten.tentenstomp.global.common.annotation.GetExecutionTime)") public Object getExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); @@ -47,7 +47,7 @@ public Object withRedissonLock(ProceedingJoinPoint joinPoint) throws Throwable { signature.getParameterNames() ); - RLock lock = redissonClient.getLock(tripId); + RLock lock = redissonClient.getLock(tripId + " " + method.getName()); long waitTime = withRedissonLock.waitTime(); long leaseTime = withRedissonLock.leaseTime(); @@ -57,8 +57,8 @@ public Object withRedissonLock(ProceedingJoinPoint joinPoint) throws Throwable { if (!available) { throw new RuntimeException(REDISSON_TIME_OUT); } - log.info("redisson lock acquired " + tripId + " thread " + Thread.currentThread().getId()); - return joinPoint.proceed(joinPoint.getArgs()); + log.info("redisson lock acquired {} thread {}", tripId, Thread.currentThread().getId()); + return redissonTransaction.proceed(joinPoint); } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); diff --git a/src/main/java/org/tenten/tentenstomp/global/component/AsyncPathComponent.java b/src/main/java/org/tenten/tentenstomp/global/component/AsyncPathComponent.java index 5f55703..28d622b 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/AsyncPathComponent.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/AsyncPathComponent.java @@ -29,7 +29,12 @@ public void calculatePath(TripPlace fromPlace, TripPlace toPlace, List pathInfoMsgs, TripPathInfoMsg infoMsg) { + pathInfoMsgs.add(infoMsg); } } diff --git a/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java b/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java index e6087fd..0c9e459 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; @Component @RequiredArgsConstructor @@ -39,7 +38,7 @@ public TripPathCalculationResult getTripPath(List tripPlaceList, Tran } else { Integer priceSum = 0; - List pathInfoMsgs = new CopyOnWriteArrayList<>(); + List pathInfoMsgs = new ArrayList<>(); for (PathCalculateRequest calculateRequest : pathCalculateRequests) { asyncPathComponent.calculatePath(calculateRequest.from(), calculateRequest.to(), pathInfoMsgs, transportation); } diff --git a/src/test/java/integrate/org/tenten/tentenstomp/domain/trip/service/TripItemServiceIntegrateTest.java b/src/test/java/integrate/org/tenten/tentenstomp/domain/trip/service/TripItemServiceIntegrateTest.java index 971792b..3ace3ed 100644 --- a/src/test/java/integrate/org/tenten/tentenstomp/domain/trip/service/TripItemServiceIntegrateTest.java +++ b/src/test/java/integrate/org/tenten/tentenstomp/domain/trip/service/TripItemServiceIntegrateTest.java @@ -110,17 +110,18 @@ void afterEach() { @DisplayName("redisson lock 테스트") public void testRedissonLock() throws Exception{ // given - int threadCount = 100; + int threadCount = 30; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); // when - int[] array = IntStream.range(0, 100).toArray(); + int[] array = IntStream.range(0, 30).toArray(); for (int i : array) { executorService.submit(() -> { try { TripItem tripItem = tripItems.get(i % tripItems.size()); Trip trip = tripItem.getTrip(); tripItemService.updateTripItemPrice(tripItem.getId().toString(), new TripItemPriceUpdateMsg(trip.getEncryptedId(), LocalDate.now().toString(), i + 100L)); + tripItem.updatePrice(i + 100L); } finally { latch.countDown(); } @@ -131,8 +132,14 @@ public void testRedissonLock() throws Exception{ Optional byEncryptedId = tripRepository.findByEncryptedId(trips.get(0).getEncryptedId()); assert byEncryptedId.isPresent(); Trip trip = byEncryptedId.get(); - log.info(String.valueOf(trip.getTripItemPriceSum())); - assert trip.getTripItemPriceSum().equals(800L - 10L); + log.info("tripPriceSum "+ String.valueOf(trip.getTripItemPriceSum())); + List items = tripItemRepository.findTripItemByTripIdAndVisitDate(trips.get(0).getEncryptedId(), LocalDate.now()); + long priceSum = 0; + for (TripItem tripItem : items) { + priceSum += tripItem.getPrice(); + } + log.info("priceSum "+priceSum); + assert trip.getTripItemPriceSum().equals(priceSum); } } \ No newline at end of file