-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21 from softeerbootcamp4th/feat/logging
[Feature] timestamp 기반 로깅 시스템 설정 및 ngrinder 테스트
- Loading branch information
Showing
11 changed files
with
207 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 5 additions & 3 deletions
8
src/main/java/com/softeer/podoarrival/event/model/dto/ArrivalApplicationResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
package com.softeer.podoarrival.event.model.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@Getter | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class ArrivalApplicationResponseDto { | ||
private String response; | ||
private boolean success; | ||
private String name; | ||
private String phoneNum; | ||
private int grade; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 2 additions & 75 deletions
77
src/main/java/com/softeer/podoarrival/event/service/ArrivalEventReleaseService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,11 @@ | ||
package com.softeer.podoarrival.event.service; | ||
|
||
import com.softeer.podoarrival.event.exception.ExistingUserException; | ||
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto; | ||
import com.softeer.podoarrival.event.model.entity.ArrivalUser; | ||
import com.softeer.podoarrival.event.model.entity.Role; | ||
import com.softeer.podoarrival.event.repository.ArrivalUserRepository; | ||
import com.softeer.podoarrival.security.AuthInfo; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.redisson.api.BatchResult; | ||
import org.redisson.api.RBatch; | ||
import org.redisson.api.RedissonClient; | ||
import org.springframework.scheduling.annotation.Async; | ||
import org.springframework.scheduling.annotation.Scheduled; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.LocalDate; | ||
import java.util.concurrent.CompletableFuture; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class ArrivalEventReleaseService { | ||
public interface ArrivalEventReleaseService { | ||
|
||
private final RedissonClient redissonClient; | ||
private final ArrivalUserRepository arrivalUserRepository; | ||
|
||
private final String ARRIVAL_SET = "arrivalset"; | ||
private boolean CHECK = false; | ||
|
||
private static int MAX_ARRIVAL = 100; // default | ||
|
||
/** | ||
* 비동기로 Redis 호출하는 메서드 | ||
* 반환값은 ArrivalEventService에서 받아서 선착순 처리 | ||
*/ | ||
@Async("arrivalExecutor") | ||
public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo authInfo) { | ||
return CompletableFuture.supplyAsync(() -> { | ||
String redisKey = LocalDate.now() + ARRIVAL_SET; | ||
|
||
if(CHECK){ | ||
return new ArrivalApplicationResponseDto("선착순 응모에 실패했습니다.", -1); | ||
} | ||
|
||
RBatch batch = redissonClient.createBatch(); | ||
batch.getSet(redisKey).addAsync(authInfo.getPhoneNum()); | ||
batch.getSet(redisKey).sizeAsync(); | ||
BatchResult<?> res = batch.execute(); | ||
|
||
//첫번째 응답 | ||
if(!(boolean) res.getResponses().get(0)){ | ||
throw new ExistingUserException("이미 응모한 전화번호입니다."); | ||
} | ||
|
||
int grade = (int) res.getResponses().get(1); | ||
// 선착순 순위에 들었다면 | ||
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("선착순 응모에 성공했습니다.", grade); | ||
} else { | ||
CHECK = true; | ||
return new ArrivalApplicationResponseDto("선착순 응모에 실패했습니다.", -1); | ||
} | ||
}); | ||
} | ||
|
||
public static void setMaxArrival(int val) { | ||
MAX_ARRIVAL = val; | ||
} | ||
|
||
public static int getMaxArrival() { | ||
return MAX_ARRIVAL; | ||
} | ||
CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo authInfo); | ||
} |
78 changes: 78 additions & 0 deletions
78
src/main/java/com/softeer/podoarrival/event/service/ArrivalEventReleaseServiceJavaImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.softeer.podoarrival.event.service; | ||
|
||
import com.softeer.podoarrival.event.exception.ExistingUserException; | ||
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto; | ||
import com.softeer.podoarrival.event.model.entity.ArrivalUser; | ||
import com.softeer.podoarrival.event.model.entity.Role; | ||
import com.softeer.podoarrival.event.repository.ArrivalUserRepository; | ||
import com.softeer.podoarrival.security.AuthInfo; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.scheduling.annotation.Async; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class ArrivalEventReleaseServiceJavaImpl implements ArrivalEventReleaseService { | ||
|
||
private final ArrivalUserRepository arrivalUserRepository; | ||
|
||
private static int MAX_ARRIVAL = 100; // default | ||
private boolean CHECK = false; | ||
|
||
private static AtomicInteger count = new AtomicInteger(1); | ||
private static ConcurrentHashMap<String, Integer> hashMap = new ConcurrentHashMap<>(); | ||
|
||
/** | ||
* 비동기와 Atomic 변수를 통해서 동시성을 처리 | ||
* Hash function 통해서 전화번호 중복을 확인 | ||
*/ | ||
@Async("arrivalExecutor") | ||
@Override | ||
public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo authInfo) { | ||
return CompletableFuture.supplyAsync(() -> { | ||
|
||
if(CHECK){ | ||
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), -1); | ||
} | ||
|
||
//첫번째 응답 | ||
if(hashMap.containsKey(authInfo.getPhoneNum())){ | ||
throw new ExistingUserException("이미 응모한 전화번호입니다."); | ||
} | ||
|
||
int grade = count.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; | ||
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), grade); | ||
} | ||
}); | ||
} | ||
|
||
public static void setMaxArrival(int val) { | ||
MAX_ARRIVAL = val; | ||
} | ||
|
||
public static int getMaxArrival() { | ||
return MAX_ARRIVAL; | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
src/main/java/com/softeer/podoarrival/event/service/ArrivalEventReleaseServiceRedisImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package com.softeer.podoarrival.event.service; | ||
|
||
import com.softeer.podoarrival.event.exception.ExistingUserException; | ||
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto; | ||
import com.softeer.podoarrival.event.model.entity.ArrivalUser; | ||
import com.softeer.podoarrival.event.model.entity.Role; | ||
import com.softeer.podoarrival.event.repository.ArrivalUserRepository; | ||
import com.softeer.podoarrival.security.AuthInfo; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.redisson.api.BatchResult; | ||
import org.redisson.api.RBatch; | ||
import org.redisson.api.RedissonClient; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.scheduling.annotation.Async; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.LocalDate; | ||
import java.util.concurrent.CompletableFuture; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class ArrivalEventReleaseServiceRedisImpl implements ArrivalEventReleaseService { | ||
|
||
private static final Logger specialLogger = LoggerFactory.getLogger("arrivalEventLogger"); | ||
|
||
private final RedissonClient redissonClient; | ||
private final ArrivalUserRepository arrivalUserRepository; | ||
|
||
private final String ARRIVAL_SET = "arrivalset"; | ||
private boolean CHECK = false; | ||
private static int MAX_ARRIVAL = 100; // default | ||
|
||
/** | ||
* 비동기로 Redis 호출하는 메서드 | ||
* Redisson set을 통해서 전화번호 중복 처리 | ||
* Redisson lock 대신 set을 사용하여 인원수 처리 | ||
*/ | ||
@Async("arrivalExecutor") | ||
@Override | ||
public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo authInfo) { | ||
return CompletableFuture.supplyAsync(() -> { | ||
String redisKey = LocalDate.now() + ARRIVAL_SET; | ||
|
||
if(CHECK){ | ||
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), -1); | ||
} | ||
|
||
RBatch batch = redissonClient.createBatch(); | ||
batch.getSet(redisKey).addAsync(authInfo.getPhoneNum()); | ||
batch.getSet(redisKey).sizeAsync(); | ||
BatchResult<?> res = batch.execute(); | ||
|
||
//첫번째 응답 | ||
if(!(boolean) res.getResponses().get(0)){ | ||
throw new ExistingUserException("이미 응모한 전화번호입니다."); | ||
} | ||
|
||
// 로깅 추가 | ||
specialLogger.info("[응모] 유저 전화번호: {}", authInfo.getPhoneNum()); | ||
|
||
int grade = (int) res.getResponses().get(1); | ||
// 선착순 순위에 들었다면 | ||
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(), grade); | ||
return new ArrivalApplicationResponseDto(true, authInfo.getName(), authInfo.getPhoneNum(), grade); | ||
} else { | ||
CHECK = true; | ||
return new ArrivalApplicationResponseDto(false, authInfo.getName(), authInfo.getPhoneNum(), grade); | ||
} | ||
}); | ||
} | ||
|
||
public static void setMaxArrival(int val) { | ||
MAX_ARRIVAL = val; | ||
} | ||
|
||
public static int getMaxArrival() { | ||
return MAX_ARRIVAL; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.