From 12d1a8a54cd000795e91577f941cfd59f894792f Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Tue, 20 Aug 2024 21:14:46 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EA=B2=B0=EA=B3=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=ED=95=B4=EB=8B=B9=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=EA=B0=80=20=EC=9D=91=EB=AA=A8=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=80=20=EA=B2=BD=EC=9A=B0=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eventService/RushEventServiceTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java index 058ceaf4..1cd3fc89 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java @@ -370,6 +370,41 @@ void getRushEventResult5() { assertFalse(result.getIsWinner()); } + @Test + @DisplayName("선착순 이벤트 결과 조회 테스트 (응모하지 않았는데 결과 조회창으로 넘어가서 호출되는 경우)") + void getRushEventResult6() { + // given + BaseUser user = new BaseUser(); + RushEventResponseDto todayEvent = new RushEventResponseDto( + 1L, + LocalDateTime.now(), + LocalDateTime.now().plusDays(1), + 315, + "image-url", + "prize-description", + new HashSet<>() + ); + + given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); + given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.empty()); + given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(500L); + given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); + + // when & then + RushEventResultResponseDto result = rushEventService.getRushEventResult(user); + + // then + assertNotNull(result); + assertNull(result.getOptionId()); + assertEquals(500, result.getLeftOption()); + assertEquals(500, result.getRightOption()); + assertNull(result.getTotalParticipants()); + assertNull(result.getRank()); + assertNull(result.getIsWinner()); + } + + @Test @DisplayName("오늘의 선착순 이벤트 DB에서 가져오기 테스트") void getTodayRushEvent() { From 1f7799d05dcf7be5a88fa51cdd8f808388cd1c85 Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:06:37 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=EC=98=A4=EB=8A=98=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A5=BC=20=EC=BA=90=EC=8B=B1?= =?UTF-8?q?=ED=95=98=EB=8A=94=20ConcurrentMapCacheManager=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CasperEvent/global/config/CacheConfig.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Server/src/main/java/JGS/CasperEvent/global/config/CacheConfig.java diff --git a/Server/src/main/java/JGS/CasperEvent/global/config/CacheConfig.java b/Server/src/main/java/JGS/CasperEvent/global/config/CacheConfig.java new file mode 100644 index 00000000..34abdd90 --- /dev/null +++ b/Server/src/main/java/JGS/CasperEvent/global/config/CacheConfig.java @@ -0,0 +1,16 @@ +package JGS.CasperEvent.global.config; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CacheConfig { + + @Bean + public CacheManager cacheManager() { + return new ConcurrentMapCacheManager("todayEventCache"); + } + +} From e87a2c6b79083316b264eb529f811f06022cb291 Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:06:57 +0900 Subject: [PATCH 3/8] =?UTF-8?q?chore:=20=EB=A9=94=EC=9D=B8=20=EC=95=A0?= =?UTF-8?q?=ED=94=8C=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=EC=97=90=20@Enabl?= =?UTF-8?q?eCaching=20=EC=95=A0=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/JGS/CasperEvent/CasperEventApplication.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/java/JGS/CasperEvent/CasperEventApplication.java b/Server/src/main/java/JGS/CasperEvent/CasperEventApplication.java index 4005d90b..07b2d937 100644 --- a/Server/src/main/java/JGS/CasperEvent/CasperEventApplication.java +++ b/Server/src/main/java/JGS/CasperEvent/CasperEventApplication.java @@ -2,12 +2,14 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableAspectJAutoProxy @EnableScheduling +@EnableCaching public class CasperEventApplication { public static void main(String[] args) { From 7980b6bbc3ce031c20068c75d3a78088f7bebabe Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:07:19 +0900 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20=EA=B8=B0=EC=A1=B4=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8D=98=20RedisTemplate=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/JGS/CasperEvent/global/config/RedisConfig.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java b/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java index ee04b77d..5b55a3f4 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java +++ b/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java @@ -37,13 +37,4 @@ public RedisTemplate CasperBotRedisTemplate(){ redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } - - @Bean - public RedisTemplate RushEventRedisTemplate(){ - RedisTemplate redisTemplate = new RedisTemplate<>(); - redisTemplate.setConnectionFactory(redisConnectionFactory()); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); - return redisTemplate; - } } From 998a7ea1f8e5f3e38f6fe25a5107acf15c128e1b Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:08:06 +0900 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=EC=98=A4=EB=8A=98=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A5=BC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20@Cacheable=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eventService/RushEventCacheService.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventCacheService.java diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventCacheService.java b/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventCacheService.java new file mode 100644 index 00000000..abb551b9 --- /dev/null +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventCacheService.java @@ -0,0 +1,39 @@ +package JGS.CasperEvent.domain.event.service.eventService; + +import JGS.CasperEvent.domain.event.dto.ResponseDto.rushEventResponseDto.RushEventResponseDto; +import JGS.CasperEvent.domain.event.entity.event.RushEvent; +import JGS.CasperEvent.domain.event.repository.eventRepository.RushEventRepository; +import JGS.CasperEvent.global.enums.CustomErrorCode; +import JGS.CasperEvent.global.error.exception.CustomException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Slf4j +public class RushEventCacheService { + + private final RushEventRepository rushEventRepository; + + @Cacheable(value = "todayEventCache", key = "#today") + public RushEventResponseDto getTodayEvent(LocalDate today) { + log.info("오늘의 이벤트 캐싱 {}", today); + // 오늘 날짜에 해당하는 모든 이벤트 꺼내옴 + List rushEventList = rushEventRepository.findByEventDate(today); + + if (rushEventList.isEmpty()) { + throw new CustomException("선착순 이벤트가 존재하지않습니다.", CustomErrorCode.NO_RUSH_EVENT); + } + + if (rushEventList.size() > 1) { + throw new CustomException("선착순 이벤트가 2개 이상 존재합니다.", CustomErrorCode.MULTIPLE_RUSH_EVENTS_FOUND); + } + + return RushEventResponseDto.of(rushEventList.get(0)); + } +} From fba10c690336e895ed53a9aa30618f09850e73e9 Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:08:40 +0900 Subject: [PATCH 6/8] =?UTF-8?q?chore:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/controller/eventController/RushEventController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java index 87756424..3ac077e1 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java @@ -73,7 +73,7 @@ public ResponseEntity rushEventResult(HttpServletReq @ApiResponse(responseCode = "204", description = "Successfully set today's event in Redis.") @GetMapping("/today/test") public ResponseEntity setTodayEvent() { - rushEventService.setTodayEventToRedis(); + rushEventService.setRushEvents(); return ResponseEntity.noContent().build(); } From febc8847e92982c15b65fb8e3eb8da1572a1aca3 Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:09:44 +0900 Subject: [PATCH 7/8] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=20Scheduler?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eventService/RushEventScheduler.java | 37 ------------ .../eventService/RushEventSchedulerTest.java | 58 ------------------- 2 files changed, 95 deletions(-) delete mode 100644 Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventScheduler.java delete mode 100644 Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventSchedulerTest.java diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventScheduler.java b/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventScheduler.java deleted file mode 100644 index 901e846c..00000000 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventScheduler.java +++ /dev/null @@ -1,37 +0,0 @@ -package JGS.CasperEvent.domain.event.service.eventService; - -import JGS.CasperEvent.domain.event.dto.ResponseDto.rushEventResponseDto.RushEventResponseDto; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -@Service -@EnableScheduling -@RequiredArgsConstructor -@Slf4j -public class RushEventScheduler { - - private final RushEventService rushEventService; - private final RedisTemplate rushEventRedisTemplate; - - // 매일 0시 1분에 스케줄된 작업을 실행합니다. - @Scheduled(cron = "0 1 0 * * ?") - public void fetchDailyEvents() { - // EventService를 통해 오늘의 이벤트를 가져옵니다. - RushEventResponseDto todayEvent = rushEventService.getTodayRushEventFromRDB(); - - // 가져온 이벤트에 대한 추가 작업을 수행합니다. - // 예: 캐싱, 로그 기록, 알림 발송 등 - rushEventRedisTemplate.opsForValue().set("todayEvent", todayEvent); - - // 로그 출력 - log.info("선착순 이벤트 스케줄러 실행: {}", LocalDateTime.now()); - log.info("가져온 이벤트 날짜: {}", todayEvent.startDateTime()); - } -} diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventSchedulerTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventSchedulerTest.java deleted file mode 100644 index 1ef8b649..00000000 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventSchedulerTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package JGS.CasperEvent.domain.event.service.eventService; - -import JGS.CasperEvent.domain.event.dto.ResponseDto.rushEventResponseDto.RushEventResponseDto; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.HashSet; - -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -@ExtendWith(MockitoExtension.class) -class RushEventSchedulerTest { - - @Mock - private RushEventService rushEventService; - - @Mock - private RedisTemplate rushEventRedisTemplate; - - @Mock - private ValueOperations valueOperations; - - @InjectMocks - private RushEventScheduler rushEventScheduler; - - @Test - void fetchDailyEvents_ShouldCacheTodayEventInRedis() { - // given - LocalDate today = LocalDate.now(); - RushEventResponseDto todayEvent = new RushEventResponseDto( - 1L, - LocalDateTime.now(), - LocalDateTime.now().plusDays(1), - 315, - "image-url", - "prize-description", - new HashSet<>() - ); - - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventService.getTodayRushEventFromRDB()).willReturn(todayEvent); - - // when - rushEventScheduler.fetchDailyEvents(); - - // then - verify(rushEventService).getTodayRushEventFromRDB(); - verify(rushEventRedisTemplate.opsForValue()).set("todayEvent", todayEvent); - } -} From 7872f3948e1b5744276b46f23a4748c93f556a59 Mon Sep 17 00:00:00 2001 From: wjddn2165 Date: Wed, 21 Aug 2024 00:10:23 +0900 Subject: [PATCH 8/8] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=20Redis?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8D=98=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9D=84=20=EB=A1=9C=EC=BB=AC=20=EC=BA=90=EC=8B=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eventService/RushEventService.java | 61 +++------- .../eventService/RushEventServiceTest.java | 113 +++--------------- 2 files changed, 35 insertions(+), 139 deletions(-) diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventService.java b/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventService.java index ae2dc171..9c3141a5 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventService.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/service/eventService/RushEventService.java @@ -13,7 +13,6 @@ import JGS.CasperEvent.global.error.exception.CustomException; import JGS.CasperEvent.global.util.RepositoryErrorHandler; import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,13 +28,15 @@ public class RushEventService { private final RushEventRepository rushEventRepository; private final RushParticipantsRepository rushParticipantsRepository; - private final RedisTemplate rushEventRedisTemplate; private final RushOptionRepository rushOptionRepository; + private final RushEventCacheService rushEventCacheService; @Transactional public RushEventListResponseDto getAllRushEvents() { + LocalDate today = LocalDate.now(); + // 오늘의 선착순 이벤트 꺼내오기 - RushEventResponseDto todayEvent = getTodayRushEventFromRedis(); + RushEventResponseDto todayEvent = rushEventCacheService.getTodayEvent(today); // DB에서 모든 RushEvent 가져오기 List rushEventList = rushEventRepository.findAll(); @@ -67,13 +68,15 @@ public RushEventListResponseDto getAllRushEvents() { // 응모 여부 조회 public boolean isExists(String userId) { - Long todayEventId = getTodayRushEventFromRedis().rushEventId(); + LocalDate today = LocalDate.now(); + Long todayEventId = rushEventCacheService.getTodayEvent(today).rushEventId(); return rushParticipantsRepository.existsByRushEvent_RushEventIdAndBaseUser_Id(todayEventId, userId); } @Transactional public void apply(BaseUser user, int optionId) { - Long todayEventId = getTodayRushEventFromRedis().rushEventId(); + LocalDate today = LocalDate.now(); + Long todayEventId = rushEventCacheService.getTodayEvent(today).rushEventId(); // 이미 응모한 회원인지 검증 if (rushParticipantsRepository.existsByRushEvent_RushEventIdAndBaseUser_Id(todayEventId, user.getId())) { @@ -90,7 +93,8 @@ public void apply(BaseUser user, int optionId) { // 진행중인 게임의 응모 비율 반환 public RushEventRateResponseDto getRushEventRate(BaseUser user) { - Long todayEventId = getTodayRushEventFromRedis().rushEventId(); + LocalDate today = LocalDate.now(); + Long todayEventId = rushEventCacheService.getTodayEvent(today).rushEventId(); Optional optionId = rushParticipantsRepository.getOptionIdByUserId(user.getId()); long leftOptionCount = rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(todayEventId, 1); long rightOptionCount = rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(todayEventId, 2); @@ -104,7 +108,8 @@ public RushEventRateResponseDto getRushEventRate(BaseUser user) { // 응모하지 않은 유저가 요청하는 경우가 존재 -> 응모 비율만 반환하도록 수정 @Transactional public RushEventResultResponseDto getRushEventResult(BaseUser user) { - RushEventResponseDto todayRushEvent = getTodayRushEventFromRedis(); + LocalDate today = LocalDate.now(); + RushEventResponseDto todayRushEvent = rushEventCacheService.getTodayEvent(today); Long todayEventId = todayRushEvent.rushEventId(); // 최종 선택 비율을 조회 @@ -157,39 +162,8 @@ public RushEventResultResponseDto getRushEventResult(BaseUser user) { return new RushEventResultResponseDto(optionId, leftOption, rightOption, rank, totalParticipants, isWinner); } - // 오늘의 이벤트를 DB에 꺼내서 반환 - public RushEventResponseDto getTodayRushEventFromRDB() { - LocalDate today = LocalDate.now(); - - // 오늘 날짜에 해당하는 모든 이벤트 꺼내옴 - List rushEventList = rushEventRepository.findByEventDate(today); - - if (rushEventList.isEmpty()) { - throw new CustomException("선착순 이벤트가 존재하지않습니다.", CustomErrorCode.NO_RUSH_EVENT); - } - - if (rushEventList.size() > 1) { - throw new CustomException("선착순 이벤트가 2개 이상 존재합니다.", CustomErrorCode.MULTIPLE_RUSH_EVENTS_FOUND); - } - - return RushEventResponseDto.of(rushEventList.get(0)); - } - - // 오늘의 이벤트 꺼내오기 - private RushEventResponseDto getTodayRushEventFromRedis() { - RushEventResponseDto todayEvent = rushEventRedisTemplate.opsForValue().get("todayEvent"); - - // Redis에 오늘의 이벤트가 없으면 DB에서 가져와서 Redis에 저장한 후 반환. - if (todayEvent == null) { - todayEvent = getTodayRushEventFromRDB(); - rushEventRedisTemplate.opsForValue().set("todayEvent", todayEvent); - } - - return todayEvent; - } - @Transactional - public void setTodayEventToRedis() { + public void setRushEvents() { // 테이블 초기화 rushParticipantsRepository.deleteAllInBatch(); rushOptionRepository.deleteAllInBatch(); @@ -253,15 +227,13 @@ public void setTodayEventToRedis() { rushEvents.add(rushEvent); } - - // 세 번째로 생성된 RushEvent를 Redis에 저장 - rushEventRedisTemplate.opsForValue().set("todayEvent", RushEventResponseDto.of(rushEvents.get(2))); } // 오늘의 이벤트 옵션 정보를 반환 public MainRushEventOptionsResponseDto getTodayRushEventOptions() { - RushEventResponseDto todayEvent = getTodayRushEventFromRedis(); + LocalDate today = LocalDate.now(); + RushEventResponseDto todayEvent = rushEventCacheService.getTodayEvent(today); Set options = todayEvent.options(); RushEventOptionResponseDto leftOption = options.stream() @@ -282,7 +254,8 @@ public MainRushEventOptionsResponseDto getTodayRushEventOptions() { public ResultRushEventOptionResponseDto getRushEventOptionResult(int optionId) { Position position = Position.of(optionId); - RushEventResponseDto todayEvent = getTodayRushEventFromRedis(); + LocalDate today = LocalDate.now(); + RushEventResponseDto todayEvent = rushEventCacheService.getTodayEvent(today); Set options = todayEvent.options(); if (options.size() != 2) { diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java index 1cd3fc89..2411c420 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java @@ -17,8 +17,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; import java.time.LocalDate; import java.time.LocalDateTime; @@ -39,12 +37,10 @@ class RushEventServiceTest { @Mock private RushParticipantsRepository rushParticipantsRepository; @Mock - private RedisTemplate rushEventRedisTemplate; - @Mock private RushOptionRepository rushOptionRepository; - @Mock - private ValueOperations valueOperations; + @Mock + private RushEventCacheService rushEventCacheService; @InjectMocks RushEventService rushEventService; @@ -70,8 +66,7 @@ void getAllRushEvents() { List mainRushEventResponseDtoList = rushEventList.stream() .map(MainRushEventResponseDto::of).toList(); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(valueOperations.get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushEventRepository.findAll()).willReturn(rushEventList); // when @@ -98,8 +93,7 @@ void isExists() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.existsByRushEvent_RushEventIdAndBaseUser_Id(1L, user.getId())).willReturn(true); // when @@ -124,8 +118,7 @@ void apply() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.existsByRushEvent_RushEventIdAndBaseUser_Id(1L, user.getId())).willReturn(false); RushEvent rushEvent = new RushEvent(); given(rushEventRepository.findById(1L)).willReturn(Optional.of(rushEvent)); @@ -152,8 +145,7 @@ void apply2() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.existsByRushEvent_RushEventIdAndBaseUser_Id(1L, user.getId())).willReturn(true); // when & then @@ -181,8 +173,7 @@ void getRushEventRate() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.of(1)); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(100L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(200L); @@ -212,8 +203,7 @@ void getRushEventResult() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.of(1)); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(700L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); @@ -247,8 +237,7 @@ void getRushEventResult2() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.of(2)); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(700L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); @@ -282,8 +271,7 @@ void getRushEventResult3() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.of(1)); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(700L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); @@ -317,8 +305,7 @@ void getRushEventResult4() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.of(1)); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(500L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); @@ -351,8 +338,7 @@ void getRushEventResult5() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.of(1)); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(500L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); @@ -385,8 +371,7 @@ void getRushEventResult6() { new HashSet<>() ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushParticipantsRepository.getOptionIdByUserId(user.getId())).willReturn(Optional.empty()); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 1)).willReturn(500L); given(rushParticipantsRepository.countByRushEvent_RushEventIdAndOptionId(1L, 2)).willReturn(500L); @@ -404,59 +389,6 @@ void getRushEventResult6() { assertNull(result.getIsWinner()); } - - @Test - @DisplayName("오늘의 선착순 이벤트 DB에서 가져오기 테스트") - void getTodayRushEvent() { - // given - LocalDate today = LocalDate.now(); - RushEvent rushEvent = new RushEvent(); - given(rushEventRepository.findByEventDate(today)).willReturn(List.of(rushEvent)); - - // when - RushEventResponseDto result = rushEventService.getTodayRushEventFromRDB(); - - // then - assertNotNull(result); - assertEquals(rushEvent.getRushEventId(), result.rushEventId()); - } - - @Test - @DisplayName("오늘의 선착순 이벤트 DB에서 가져오기 테스트 (RDB에 선착순 이벤트가 없는 경우)") - void getTodayRushEvent2() { - // given - LocalDate today = LocalDate.now(); - given(rushEventRepository.findByEventDate(today)).willReturn(List.of()); - - // when & then - CustomException exception = assertThrows(CustomException.class, () -> - rushEventService.getTodayRushEventFromRDB() - ); - - assertEquals(CustomErrorCode.NO_RUSH_EVENT, exception.getErrorCode()); - assertEquals("선착순 이벤트가 존재하지않습니다.", exception.getMessage()); - } - - @Test - @DisplayName("오늘의 선착순 이벤트 DB에서 가져오기 테스트 (RDB에 선착순 이벤트가 2개 이상인 경우)") - void getTodayRushEvent3() { - // given - LocalDate today = LocalDate.now(); - RushEvent rushEvent1 = new RushEvent(); - RushEvent rushEvent2 = new RushEvent(); - given(rushEventRepository.findByEventDate(today)).willReturn(List.of( - rushEvent1, rushEvent2 - )); - - // when & then - CustomException exception = assertThrows(CustomException.class, () -> - rushEventService.getTodayRushEventFromRDB() - ); - - assertEquals(CustomErrorCode.MULTIPLE_RUSH_EVENTS_FOUND, exception.getErrorCode()); - assertEquals("선착순 이벤트가 2개 이상 존재합니다.", exception.getMessage()); - } - @Test @DisplayName("선착순 이벤트 테스트 API 테스트") void setTodayEventToRedis() { @@ -465,16 +397,14 @@ void setTodayEventToRedis() { RushOption rushOption = new RushOption(); given(rushEventRepository.save(any(RushEvent.class))).willReturn(rushEvent); given(rushOptionRepository.save(any(RushOption.class))).willReturn(rushOption); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); // when - rushEventService.setTodayEventToRedis(); + rushEventService.setRushEvents(); // then verify(rushParticipantsRepository).deleteAllInBatch(); verify(rushOptionRepository).deleteAllInBatch(); verify(rushEventRepository).deleteAllInBatch(); - verify(rushEventRedisTemplate.opsForValue()).set(eq("todayEvent"), any(RushEventResponseDto.class)); } @Test @@ -494,8 +424,7 @@ void getTodayRushEventOptions() { ) ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); // when MainRushEventOptionsResponseDto result = rushEventService.getTodayRushEventOptions(); @@ -524,9 +453,7 @@ void getRushEventOptionResult() { ) ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); - + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); // when ResultRushEventOptionResponseDto result = rushEventService.getRushEventOptionResult(optionId); @@ -554,9 +481,7 @@ void getRushEventOptionResult2() { ) ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); - + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); // when & then CustomException exception = assertThrows(CustomException.class, () -> rushEventService.getRushEventOptionResult(optionId) @@ -611,9 +536,7 @@ void getRushEventOptionResult4() { ) ); - given(rushEventRedisTemplate.opsForValue()).willReturn(valueOperations); - given(rushEventRedisTemplate.opsForValue().get("todayEvent")).willReturn(todayEvent); - + given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); // when & then CustomException exception = assertThrows(CustomException.class, () -> rushEventService.getRushEventOptionResult(optionId)