Skip to content

Commit

Permalink
feat : 숨캐찾 게임 참여자 카운트를 스케줄링을 통해 0으로 만드는 로직 (CC-184) (#54)
Browse files Browse the repository at this point in the history
* feat : 주기적으 숨캐찾 게임 참여자 레디스 카운트를 0으로 만들기
 (CC-184)

* refactor : 주기적으로 winner를 삭제하는 로직을 서비스 계층으로 이관
 (CC-184)

* fix : 버그 수정 주석 제시
 (CC-184)

* fix : 스케줄링 시간을 매 5분으로 수정
 (CC-184)
  • Loading branch information
j2noo authored Aug 24, 2024
1 parent 4767a58 commit c794557
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package ai.softeer.caecae.findinggame.repository;

import ai.softeer.caecae.findinggame.domain.entity.FindingGameRealWinner;
import ai.softeer.caecae.global.utils.SystemTimeConvertor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.Map;

@Slf4j
Expand Down Expand Up @@ -97,29 +94,14 @@ public FindingGameRealWinner getFrontRealWinner() {
return (FindingGameRealWinner) redisTemplate.opsForList().index(REAL_WINNER_KEY, 0);
}

public Map<Object, Object> getAllWinner() {
return redisTemplate.opsForHash().entries(WINNER_KEY);
}

/**
* 정답을 모두 맞추었지만 전화번호를 입력하지 않은 winner의 데이터를 주기적으로 삭제한다.
* count 값을 0으로 초기화 하는 메서드
*/
@Scheduled(cron = "* */5 * * * *") // 매 5분마다 실행
public void deleteUnregisteredWinner() {
Map<Object, Object> entries = redisTemplate.opsForHash().entries(WINNER_KEY);
for (Map.Entry<Object, Object> entry : entries.entrySet()) {
String ticketId = entry.getKey().toString();
Long startTime = (Long) entry.getValue();
Long diffTime = System.currentTimeMillis() - startTime;

if (diffTime > 1000 * 60 * 3) {
LocalDateTime convertedStartTime = SystemTimeConvertor.convertToLocalDateTime(startTime);
LocalDateTime now = SystemTimeConvertor.convertToLocalDateTime(System.currentTimeMillis());

deleteWinner(ticketId);
Long count = decreaseCount();

log.info("[DELETED] UUID : " + ticketId);
log.info("[DELETED] 정답을 맞춘 시간: " + convertedStartTime);
log.info("[DELETED] 현재 시간 : " + now);
log.info("current count : " + count);
}
}
public void initDailyWinnerCount() {
redisTemplate.opsForValue().set(COUNT_KEY, 0);
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package ai.softeer.caecae.findinggame.service;

import ai.softeer.caecae.findinggame.domain.entity.FindingGame;
import ai.softeer.caecae.findinggame.domain.entity.FindingGameRealWinner;
import ai.softeer.caecae.findinggame.domain.entity.FindingGameWinner;
import ai.softeer.caecae.findinggame.repository.FindingGameDbRepository;
import ai.softeer.caecae.findinggame.repository.FindingGameRedisRepository;
import ai.softeer.caecae.global.utils.SystemTimeConvertor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.Clock;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class FindingGameScheduleService {
private final FindingGameRedisRepository findingGameRedisRepository;
private final FindingGamePlayService findingGamePlayService;
private final FindingGameDbRepository findingGameDbRepository;
private final Clock clock;

private final int TRANSACTION_COUNT = 50;

Expand All @@ -42,4 +50,55 @@ public void insertWinnerToDatabaseScheduler() {
log.info("선착순 인원 스케쥴링 처리 완료 - {} 건", completed);
}
}

/**
* 정답을 모두 맞추었지만 전화번호를 입력하지 않은 winner의 데이터를 주기적으로 삭제한다.
*/
@Scheduled(cron = "0 */5 * * * *") // 매 5분마다 실행
public void deleteUnregisteredWinner() {
Map<Object, Object> winners = findingGameRedisRepository.getAllWinner();
for (Map.Entry<Object, Object> entry : winners.entrySet()) {
String ticketId = entry.getKey().toString();
Long startTime = (Long) entry.getValue();
Long diffTime = System.currentTimeMillis() - startTime;

if (diffTime > 1000 * 60 * 3) {
LocalDateTime convertedStartTime = SystemTimeConvertor.convertToLocalDateTime(startTime);
LocalDateTime now = SystemTimeConvertor.convertToLocalDateTime(System.currentTimeMillis());

findingGameRedisRepository.deleteWinner(ticketId);
Long count = findingGameRedisRepository.decreaseCount();

log.info("[DELETED] UUID : " + ticketId);
log.info("[DELETED] 정답을 맞춘 시간: " + convertedStartTime);
log.info("[DELETED] 현재 시간 : " + now);
log.info("current count : " + count);
}
}
}

/**
* 10분마다 count의 값을 0으로 초기화하는 메서드
*/
@Scheduled(cron = "59 */10 * * * *")
public void initDailyWinnerCountScheduler() {
List<FindingGame> findingGames = findingGameDbRepository.findAllOrderByStartTimeCacheable();
LocalDateTime now = LocalDateTime.now(clock);
Boolean isFindingGamePlayable = false;

for (FindingGame findingGame : findingGames) {
if (findingGame.getStartTime().isBefore(now) && findingGame.getEndTime().isAfter(now)) {
isFindingGamePlayable = true;
break;
}
}

if (!isFindingGamePlayable) {
findingGameRedisRepository.initDailyWinnerCount();
log.info("Init FindingGame count to 0");
}

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public StartGameResponseDto startFindingGame() {

HashMap<String, String> infoHashMap = new HashMap<>();

//TODO: nextGameIndex == -1 이면 에러 수정
FindingGameDailyInfo nextGameInfo = dto.findingGameInfos().get(nextGameIndex);
LocalDateTime nowTime = LocalDateTime.now(clock);
// 캐싱으로 인해 다음 게임이 이미 시작된 경우를 확인
Expand Down

0 comments on commit c794557

Please sign in to comment.