-
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.
- volatile의 쓰기 이슈로 인해 AtomicInteger 사용
- Loading branch information
Showing
1 changed file
with
91 additions
and
0 deletions.
There are no files selected for viewing
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; | ||
} | ||
} |