Skip to content

Commit

Permalink
Merge pull request #33 from softeerbootcamp4th/feat/stress-tests
Browse files Browse the repository at this point in the history
[Feature] 동기 부하테스트 코드 백업
  • Loading branch information
eckrin authored Sep 12, 2024
2 parents 3c3f391 + deb86fd commit 7f94997
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/main/java/com/softeer/podoarrival/config/AsyncConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class AsyncConfig {
@Bean(name = "arrivalExecutor")
public Executor arrivalExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20); // 초기 스레드 풀 크기
executor.setMaxPoolSize(100); // 최대 스레드 풀 크기
executor.setCorePoolSize(50); // 초기 스레드 풀 크기
executor.setMaxPoolSize(300); // 최대 스레드 풀 크기
executor.setQueueCapacity(300000); // 대기열 크기
executor.setThreadNamePrefix("Async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // reject시 처리정책 - 시간이 걸려도 처리
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public class ArrivalEventSyncController {
// @PostMapping("/application")
@Operation(summary = "선착순 응모용 Api")
public CommonResponse<ArrivalApplicationResponseDto> arrivalEventApplication(@Auth AuthInfo authInfo) {
return new CommonResponse<>(arrivalEventSyncService.applyEvent(authInfo));
return new CommonResponse<>(arrivalEventSyncService.applyEventWithRedis(authInfo));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
import com.softeer.podoarrival.event.model.entity.ArrivalUser;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface ArrivalUserRepository extends JpaRepository<ArrivalUser, Long> {
Optional<ArrivalUser> findByPhoneNum(String phoneNum);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.softeer.podoarrival.event.service;

import com.softeer.podoarrival.event.exception.EventClosedException;
import com.softeer.podoarrival.event.exception.ExistingUserException;
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto;
import com.softeer.podoarrival.event.model.entity.ArrivalUser;
Expand All @@ -14,8 +15,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Service
Expand All @@ -29,9 +36,14 @@ public class ArrivalEventSyncService {
private boolean CHECK = false;

private final String ARRIVAL_SET = "arrivalset";
private static int MAX_ARRIVAL = 30000; // default
private static int MAX_ARRIVAL = 40000; // default
private static int count = 1;

public ArrivalApplicationResponseDto applyEvent(AuthInfo authInfo) {
private static AtomicInteger countAtomic = new AtomicInteger(1);
private static ConcurrentHashMap<String, Integer> hashMap = new ConcurrentHashMap<>();


public ArrivalApplicationResponseDto applyEventWithRedis(AuthInfo authInfo) {
String redisKey = LocalDate.now() + ARRIVAL_SET;

if(CHECK){
Expand Down Expand Up @@ -61,11 +73,71 @@ public ArrivalApplicationResponseDto applyEvent(AuthInfo authInfo) {
.build()
);
log.info("[당첨] 유저 전화번호 = {}, 등수 = {}", authInfo.getPhoneNum(), grade);
try {
Thread.sleep(15);
} catch (InterruptedException e) {
throw new RuntimeException(e);
// try {
// Thread.sleep(15);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
return new ArrivalApplicationResponseDto(true, authInfo.getName(), authInfo.getPhoneNum(), grade);
} else {
CHECK = true;
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), grade);
}
}

@Transactional
public synchronized ArrivalApplicationResponseDto applyEventWithSynchronized(AuthInfo authInfo) {

if(CHECK){
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), -1);
}

Optional<ArrivalUser> findUser = arrivalUserRepository.findByPhoneNum(authInfo.getPhoneNum());

int grade = count++;
if(grade<=MAX_ARRIVAL) {
if(findUser.isEmpty()) {
arrivalUserRepository.save(
ArrivalUser.builder()
.name(authInfo.getName())
.phoneNum(authInfo.getPhoneNum())
.role(Role.ROLE_USER)
.arrivalRank(grade)
.build()
);
return new ArrivalApplicationResponseDto(true, authInfo.getName(), authInfo.getPhoneNum(), grade);
} else {
throw new ExistingUserException("이미 응모한 전화번호입니다.");
}
} else {
CHECK = true;
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), grade);
}
}

@Transactional
public ArrivalApplicationResponseDto applyEventWithJava(AuthInfo authInfo) {
if(CHECK){
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), -1);
}

//첫번째 응답
if(hashMap.containsKey(authInfo.getPhoneNum())){
throw new ExistingUserException("이미 응모한 전화번호입니다.");
}

int grade = countAtomic.getAndIncrement();
// 선착순 순위에 들었다면
if(grade <= MAX_ARRIVAL){
arrivalUserRepository.save(
ArrivalUser.builder()
.name(authInfo.getName())
.phoneNum(authInfo.getPhoneNum())
.role(Role.ROLE_USER)
.arrivalRank(grade)
.build()
);
log.info("전화번호 = {}", authInfo.getPhoneNum());
return new ArrivalApplicationResponseDto(true, authInfo.getName(), authInfo.getPhoneNum(), grade);
} else {
CHECK = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import java.text.ParseException;
import java.util.Base64;
import java.util.Date;

@Component
public class TokenProvider {
Expand All @@ -38,7 +39,14 @@ public JWTClaimsSet validateTokenAndGetClaimsSet(String token) {
throw new InvalidTokenException("Token signature is invalid");
}

return signedJWT.getJWTClaimsSet();
JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet();
// expirationTime 검증
Date expirationTime = claimsSet.getExpirationTime();
if (expirationTime == null || expirationTime.before(new Date())) {
throw new InvalidTokenException("이미 만료된 토큰입니다.");
}

return claimsSet;

} catch (JOSEException | ParseException e) {
throw new InvalidTokenException("JWE Token Decoding Error - 토큰 검증과정에서 오류 발생");
Expand Down

0 comments on commit 7f94997

Please sign in to comment.