Skip to content

Commit

Permalink
Merge pull request #151 from Media-XI/fix/concurrent-test-issue-fix
Browse files Browse the repository at this point in the history
동시성 테스트 실패 문제 해결
  • Loading branch information
Hoon9901 authored Mar 18, 2024
2 parents f2b0a4a + 1b02859 commit 4e4f57e
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;

/**
* <p>분산 락을 사용하기 위한 어노테이션</p>
* key : Lock 을 구분하기 위한 key <br>
* waitTime : 락을 얻기 위해 대기하는 시간 <br>
* leaseTime : 락을 얻은 후 유지하는 시간 <br>
* timeUnit : 시간 단위 <br>
* transactional : 트랜잭션을 사용할지 여부 <br>
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributedLock {
String key() default "";
long waitTime() default 5;
long leaseTime() default 2;
TimeUnit timeUnit() default TimeUnit.SECONDS;
boolean transactional() default true;
}
14 changes: 9 additions & 5 deletions src/main/java/com/example/codebase/aop/DistributedLockAop.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

@Aspect
@Component
Expand All @@ -33,9 +32,7 @@ public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
DistributedLock distributedLock = method.getAnnotation(DistributedLock.class);
if (distributedLock == null) {
return aopForTransaction.proceed(joinPoint);
}

String key = REDISSON_LOCK_PREFIX + CustomSpringELParser.getDynamicValue(signature.getParameterNames(), joinPoint.getArgs(), distributedLock.key());
RLock rLock = redissonClient.getLock(key);
try {
Expand All @@ -44,7 +41,7 @@ public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable {
log.info("Redisson Lock Not Available serviceName : {} key : {}", method.getName(), key);
throw new IllegalArgumentException();

Check warning on line 42 in src/main/java/com/example/codebase/aop/DistributedLockAop.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/example/codebase/aop/DistributedLockAop.java#L41-L42

Added lines #L41 - L42 were not covered by tests
}
return aopForTransaction.proceed(joinPoint);
return proceed(distributedLock, joinPoint);
} catch (InterruptedException e) {
throw new InterruptedException();

Check warning on line 46 in src/main/java/com/example/codebase/aop/DistributedLockAop.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/example/codebase/aop/DistributedLockAop.java#L45-L46

Added lines #L45 - L46 were not covered by tests
} finally {
Expand All @@ -56,6 +53,13 @@ public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable {
}
}

private Object proceed(DistributedLock distributedLock, ProceedingJoinPoint joinPoint) throws Throwable {
if (distributedLock.transactional()) {
return aopForTransaction.proceed(joinPoint);
}
return joinPoint.proceed();

Check warning on line 60 in src/main/java/com/example/codebase/aop/DistributedLockAop.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/example/codebase/aop/DistributedLockAop.java#L60

Added line #L60 was not covered by tests
}

static class CustomSpringELParser {
private CustomSpringELParser() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public class Post {
@Column(name = "created_time")
private LocalDateTime createdTime;

@Version
@Column(name = "updated_time")
private LocalDateTime updatedTime;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ public PostWithLikesResponseDTO getPost(String loginUsername, Long postId) {

// @Transactional(isolation = Isolation.SERIALIZABLE) //
@DistributedLock(key = "#postId")
@Transactional
public PostResponseDTO likePost(Long postId, String loginUsername) {
if (isDuplicatedRequest(postId, loginUsername)) {
throw new LikePostDuplicatedRequestException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ public Post createPost() {
}


@DisplayName("2명 이상의 사용자가 동시에 좋아요 요청 시")
@DisplayName("2명 이상의 사용자가 동시에 좋아요 요청 시 - 100명 동시 요청")
@Test
void test1() throws Exception {
// given
Post post = createPost();
int threadCount = 5;
int threadCount = 100;

List<Member> members = new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
Expand All @@ -103,6 +103,7 @@ void test1() throws Exception {
executorService.execute(() -> {
try {
PostResponseDTO dto = postService.likePost(post.getId(), members.get(i).getUsername());
assertEquals(true, dto.getIsLiked());
} finally {
latch.countDown();
}
Expand Down Expand Up @@ -131,7 +132,6 @@ void test2() throws Exception {
Thread.sleep(500);
executorService.execute(() -> {
PostResponseDTO dto = postService.likePost(post.getId(), member.getUsername());
System.out.println(i + " " + dto.getLikes());
latch.countDown();
});
} catch (InterruptedException e) {
Expand Down

0 comments on commit 4e4f57e

Please sign in to comment.