Skip to content

Commit

Permalink
feat: spring retry 적용헤 재시도 로직 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
pminsung12 committed Nov 19, 2024
1 parent 37ac483 commit c49fd0e
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 25 deletions.
5 changes: 5 additions & 0 deletions usecase/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ dependencies {
because("@Transactional을 위해 추가")
}

// spring retry
implementation("org.springframework.retry:spring-retry")
implementation("org.springframework:spring-aspects")


// Mixpanel
implementation("com.mixpanel:mixpanel-java:_")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@
import org.depromeet.spot.usecase.port.out.review.ReviewLikeRepository;
import org.depromeet.spot.usecase.port.out.review.ReviewRepository;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@Builder
@Transactional
Expand All @@ -25,35 +30,14 @@ public class ReviewLikeService implements ReviewLikeUsecase {
private final UpdateReviewUsecase updateReviewUsecase;
private final ReviewLikeRepository reviewLikeRepository;
private final ReviewRepository reviewRepository;
private static final int MAX_RETRY_COUNT = 3;

@Override
@Transactional
@Retryable(
retryFor = ObjectOptimisticLockingFailureException.class,
maxAttempts = 4,
backoff = @Backoff(delay = 100))
public boolean toggleLike(final Long memberId, final long reviewId) {
int retryCount = 0;
while (retryCount < MAX_RETRY_COUNT) {
try {
return tryToggleLike(memberId, reviewId);
} catch (ObjectOptimisticLockingFailureException e) {
retryCount++;
if (retryCount == MAX_RETRY_COUNT) {
throw new ConcurrentModificationException(
"좋아요 처리 중 충돌이 발생했습니다. 잠시 후 다시 시도해주세요.");
}
// 잠시 대기 후 재시도
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("처리가 중단되었습니다.", ie);
}
}
}

return false;
}

private boolean tryToggleLike(final Long memberId, final long reviewId) {
boolean exists = reviewLikeRepository.existsBy(memberId, reviewId);

if (exists) {
Expand All @@ -67,4 +51,16 @@ private boolean tryToggleLike(final Long memberId, final long reviewId) {
reviewRepository.updateLikesCount(reviewId, true);
return true;
}

// 예외 처리를 위한 Recovery 메소드
@Recover
public boolean recoverToggleLike(
ObjectOptimisticLockingFailureException e, Long memberId, long reviewId) {
log.error(
"Failed to toggle like after 3 attempts for memberId: {} and reviewId: {}",
memberId,
reviewId,
e);
throw new ConcurrentModificationException("좋아요 처리 중 충돌이 발생했습니다. 잠시 후 다시 시도해주세요.");
}
}
4 changes: 4 additions & 0 deletions versions.properties
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ version.org.testcontainers..mysql=1.20.1
version.org.testcontainers..jdbc=1.20.1

version.io.awspring.cloud..spring-cloud-starter-aws-secrets-manager-config=2.4.4

versions.org.springframework.retry..spring-retry=2.0.3

versions.org.springframework..spring-aspects=6.1.3

0 comments on commit c49fd0e

Please sign in to comment.