From c7945578603f5c37fcf409ac32005e366450c67c Mon Sep 17 00:00:00 2001 From: Jinwoo Park Date: Sat, 24 Aug 2024 23:53:09 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=EC=88=A8=EC=BA=90=EC=B0=BE=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=B0=B8=EC=97=AC=EC=9E=90=20=EC=B9=B4?= =?UTF-8?q?=EC=9A=B4=ED=8A=B8=EB=A5=BC=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=A7=81=EC=9D=84=20=ED=86=B5=ED=95=B4=200=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EB=A7=8C=EB=93=9C=EB=8A=94=20=EB=A1=9C=EC=A7=81=20(CC-184)?= =?UTF-8?q?=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat : 주기적으 숨캐찾 게임 참여자 레디스 카운트를 0으로 만들기 (CC-184) * refactor : 주기적으로 winner를 삭제하는 로직을 서비스 계층으로 이관 (CC-184) * fix : 버그 수정 주석 제시 (CC-184) * fix : 스케줄링 시간을 매 5분으로 수정 (CC-184) --- .../FindingGameRedisRepository.java | 32 +++------- .../service/FindingGameScheduleService.java | 59 +++++++++++++++++++ .../service/FindingGameService.java | 1 + 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java b/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java index 0879738..0b5754d 100644 --- a/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java +++ b/src/main/java/ai/softeer/caecae/findinggame/repository/FindingGameRedisRepository.java @@ -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 @@ -97,29 +94,14 @@ public FindingGameRealWinner getFrontRealWinner() { return (FindingGameRealWinner) redisTemplate.opsForList().index(REAL_WINNER_KEY, 0); } + public Map getAllWinner() { + return redisTemplate.opsForHash().entries(WINNER_KEY); + } + /** - * 정답을 모두 맞추었지만 전화번호를 입력하지 않은 winner의 데이터를 주기적으로 삭제한다. + * count 값을 0으로 초기화 하는 메서드 */ - @Scheduled(cron = "* */5 * * * *") // 매 5분마다 실행 - public void deleteUnregisteredWinner() { - Map entries = redisTemplate.opsForHash().entries(WINNER_KEY); - for (Map.Entry 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); } } diff --git a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameScheduleService.java b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameScheduleService.java index d20fc34..c141e3a 100644 --- a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameScheduleService.java +++ b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameScheduleService.java @@ -1,15 +1,21 @@ 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 @@ -17,6 +23,8 @@ 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; @@ -42,4 +50,55 @@ public void insertWinnerToDatabaseScheduler() { log.info("선착순 인원 스케쥴링 처리 완료 - {} 건", completed); } } + + /** + * 정답을 모두 맞추었지만 전화번호를 입력하지 않은 winner의 데이터를 주기적으로 삭제한다. + */ + @Scheduled(cron = "0 */5 * * * *") // 매 5분마다 실행 + public void deleteUnregisteredWinner() { + Map winners = findingGameRedisRepository.getAllWinner(); + for (Map.Entry 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 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"); + } + + } + + } diff --git a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java index 7d0fbd5..a4c91d0 100644 --- a/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java +++ b/src/main/java/ai/softeer/caecae/findinggame/service/FindingGameService.java @@ -76,6 +76,7 @@ public StartGameResponseDto startFindingGame() { HashMap infoHashMap = new HashMap<>(); + //TODO: nextGameIndex == -1 이면 에러 수정 FindingGameDailyInfo nextGameInfo = dto.findingGameInfos().get(nextGameIndex); LocalDateTime nowTime = LocalDateTime.now(clock); // 캐싱으로 인해 다음 게임이 이미 시작된 경우를 확인