diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/SseEmitterRepository.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/SseEmitterRepository.java index 5f184d0b..e1292a4f 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/SseEmitterRepository.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/SseEmitterRepository.java @@ -26,4 +26,8 @@ public SseEmitter findByMemberId(Member member) { public Collection findAll() { return sseEmitters.values(); } + + public boolean existByMember(Member member) { + return sseEmitters.containsKey(member.getId()); + } } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/service/notification/NotificationService.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/service/notification/NotificationService.java index d01f99c9..dedb68d3 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/service/notification/NotificationService.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/service/notification/NotificationService.java @@ -68,7 +68,6 @@ public SseEmitter createSseEmitter(Long timeout) { return new SseEmitter(timeout); } - /** * @param notificationId 알림 ID * @param authentication 회원 정보 @@ -264,6 +263,13 @@ private void sendUnreadNotifications(Member findMember, SseEmitter sseEmitter) { } private SseEmitter addClient(Member findMember) { + // 구독자 존재 여부 확인 + boolean isExists = sseEmitterRepository.existByMember(findMember); + + if (isExists) { + return sseEmitterRepository.findByMemberId(findMember); + } + // 구독자 생성 SseEmitter sseEmitter = createSseEmitter(TIMEOUT); sseEmitterRepository.save(findMember, sseEmitter); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/notification/MockNotificationServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/notification/MockNotificationServiceTest.java index f5c3d34b..28e505c1 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/notification/MockNotificationServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/notification/MockNotificationServiceTest.java @@ -1,6 +1,7 @@ package com.dreamypatisiel.devdevdev.domain.service.notification; import static com.dreamypatisiel.devdevdev.domain.service.notification.NotificationService.UNREAD_NOTIFICATION_FORMAT; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; @@ -135,6 +136,29 @@ void addClientAndSendNotificationIoException(Long unreadNotificationCount) throw verify(sseEmitterRepository).remove(mockMember); } + @ParameterizedTest + @ValueSource(longs = {1, 2, 10, 50, 100}) + @DisplayName("구독자가 이미 존재하는 경우 기존의 SSEmitter 를 반환합니다.") + void addClientAndSendNotificationIsExistMember(Long unreadNotificationCount) throws IOException { + // given + Authentication mockAuthentication = mock(Authentication.class); + Member mockMember = mock(Member.class); + SseEmitter realEmitter = new SseEmitter(); + SseEmitter spyEmitter = spy(realEmitter); + + given(timeProvider.getLocalDateTimeNow()).willReturn(LocalDateTime.of(2025, 1, 1, 0, 0, 0)); + given(memberProvider.getMemberByAuthentication(mockAuthentication)).willReturn(mockMember); + given(sseEmitterRepository.save(mockMember, spyEmitter)).willReturn(spyEmitter); + given(sseEmitterRepository.existByMember(mockMember)).willReturn(true); + given(sseEmitterRepository.findByMemberId(mockMember)).willReturn(spyEmitter); + + // when + SseEmitter sseEmitter = notificationService.addClientAndSendNotification(mockAuthentication); + + // then + assertThat(sseEmitter).isEqualTo(spyEmitter); + } + @Test @DisplayName("구독자에게 알림을 전송합니다.") void sendNotification() throws IOException {