From 03fc7da50c3be8d5ea9d986e171b5027b1fc9708 Mon Sep 17 00:00:00 2001 From: yonghwankim-dev Date: Tue, 28 May 2024 15:41:22 +0900 Subject: [PATCH] =?UTF-8?q?#333=20feat:=20=EC=A2=85=EB=AA=A9=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=EA=B0=80=20=EC=95=8C=EB=A6=BC=20=EB=A1=9C=EC=A7=81=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 - 알림 발송 -> 알림 저장이 아닌 알림 저장 -> 알림 발송으로 변경 - 알림 발송에 실패해도 알림 저장이 되도록 변경 --- secret | 2 +- .../service/NotificationService.java | 43 ++++++++++++------- .../TargetPriceNotifyMessageItem.java | 2 +- src/main/resources/application-test.yml | 1 + .../service/NotificationServiceTest.java | 13 +++--- .../service/PortfolioHoldingServiceTest.java | 5 +++ 6 files changed, 43 insertions(+), 23 deletions(-) diff --git a/secret b/secret index 0104083be..496921025 160000 --- a/secret +++ b/secret @@ -1 +1 @@ -Subproject commit 0104083be091e9ecda4a426d5678456141b8d339 +Subproject commit 49692102594713e1f45268167dc1b166a0a1b708 diff --git a/src/main/java/codesquad/fineants/domain/notification/service/NotificationService.java b/src/main/java/codesquad/fineants/domain/notification/service/NotificationService.java index 4b3abb9c9..61ae1fbc6 100644 --- a/src/main/java/codesquad/fineants/domain/notification/service/NotificationService.java +++ b/src/main/java/codesquad/fineants/domain/notification/service/NotificationService.java @@ -3,11 +3,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +import org.apache.logging.log4j.util.Strings; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -195,7 +197,7 @@ public TargetPriceNotifyMessageResponse notifyTargetPriceBy(List tickerS .map(StockTargetPrice::getTargetPriceNotifications) .flatMap(Collection::stream) .collect(Collectors.toList()); - Function sentFunction = item -> { + Function sentFunction = item -> { sentManager.addTargetPriceSendHistory(item.getTargetPriceNotificationId()); return item; }; @@ -215,7 +217,7 @@ public TargetPriceNotifyMessageResponse notifyTargetPriceBy(Long memberId) { .flatMap(Collection::stream) .collect(Collectors.toList()); - Function sentFunction = item -> { + Function sentFunction = item -> { sentManager.addTargetPriceSendHistory(item.getTargetPriceNotificationId()); return item; }; @@ -229,7 +231,7 @@ public TargetPriceNotifyMessageResponse notifyTargetPriceBy(Long memberId) { private TargetPriceNotifyMessageResponse notifyTargetPrice( List targetPrices, NotificationPolicy policy, - Function sentFunction) { + Function sentFunction) { log.debug("종목 지정가 알림 발송 서비스 시작, targetPrices={}", targetPrices); // 지정가 알림별 FCM 토큰 리스트맵 생성 @@ -249,30 +251,39 @@ private TargetPriceNotifyMessageResponse notifyTargetPrice( } log.debug("notifyMessage : {}", notifyMessages); + // 알림 저장 + List notificationSaveResponse = notifyMessages.stream() + .distinct() + // 알림 저장 + .map(message -> this.saveNotification(StockNotificationRequest.from(message))) + // 발송 이력 저장 + .map(sentFunction) + .sorted(Comparator.comparing(TargetPriceNotificationResponse::getReferenceId)) + .collect(Collectors.toList()); + log.debug("종목 지정가 알림 발송 서비스 결과, notificationSaveResponse={}", notificationSaveResponse); + // 알림 전송 + Map messageIdMap = new HashMap<>(); List sentNotifyMessages = new ArrayList<>(); for (NotifyMessage notifyMessage : notifyMessages) { firebaseMessagingService.send(notifyMessage.toMessage()) .ifPresentOrElse( - messageId -> sentNotifyMessages.add(SentNotifyMessage.create(notifyMessage, messageId)), + messageId -> { + messageIdMap.put(notifyMessage.getReferenceId(), messageId); + sentNotifyMessages.add(SentNotifyMessage.create(notifyMessage, messageId)); + }, () -> fcmService.deleteToken(notifyMessage.getToken())); } + log.info("종목 지정가 FCM 알림 발송 결과, sentNotifyMessage={}", sentNotifyMessages); - // 알림 저장 - List items = sentNotifyMessages.stream() - .distinct() - // 알림 저장 - .map(message -> { - TargetPriceNotificationResponse response = this.saveNotification( - StockNotificationRequest.from(message.getNotifyMessage())); - String messageId = message.getMessageId(); + // 응답 리스폰스 생성 + List items = notificationSaveResponse.stream() + .map(response -> { + String messageId = messageIdMap.getOrDefault(response.getReferenceId(), Strings.EMPTY); return TargetPriceNotifyMessageItem.from(response, messageId); }) - // 발송 이력 저장 - .map(sentFunction) - .sorted(Comparator.comparing(TargetPriceNotifyMessageItem::getReferenceId)) .collect(Collectors.toList()); - log.debug("종목 지정가 알림 발송 서비스 결과, items={}", items); + return TargetPriceNotifyMessageResponse.from(items); } diff --git a/src/main/java/codesquad/fineants/domain/stock_target_price/domain/dto/response/TargetPriceNotifyMessageItem.java b/src/main/java/codesquad/fineants/domain/stock_target_price/domain/dto/response/TargetPriceNotifyMessageItem.java index 248c6d563..d00df0e99 100644 --- a/src/main/java/codesquad/fineants/domain/stock_target_price/domain/dto/response/TargetPriceNotifyMessageItem.java +++ b/src/main/java/codesquad/fineants/domain/stock_target_price/domain/dto/response/TargetPriceNotifyMessageItem.java @@ -1,8 +1,8 @@ package codesquad.fineants.domain.stock_target_price.domain.dto.response; import codesquad.fineants.domain.common.money.Money; -import codesquad.fineants.domain.notification.domain.entity.type.NotificationType; import codesquad.fineants.domain.notification.domain.dto.response.TargetPriceNotificationResponse; +import codesquad.fineants.domain.notification.domain.entity.type.NotificationType; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 587533f99..1545cdd06 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -2,6 +2,7 @@ spring: datasource: hikari: leak-detection-threshold: 2000 + connection-timeout: 30000 jpa: database: mysql database-platform: org.hibernate.dialect.MySQL8Dialect diff --git a/src/test/java/codesquad/fineants/domain/notification/service/NotificationServiceTest.java b/src/test/java/codesquad/fineants/domain/notification/service/NotificationServiceTest.java index e0d6b659a..e49f676f4 100644 --- a/src/test/java/codesquad/fineants/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/codesquad/fineants/domain/notification/service/NotificationServiceTest.java @@ -29,6 +29,7 @@ import codesquad.fineants.domain.fcm_token.domain.entity.FcmToken; import codesquad.fineants.domain.fcm_token.repository.FcmRepository; import codesquad.fineants.domain.fcm_token.service.FirebaseMessagingService; +import codesquad.fineants.domain.kis.aop.AccessTokenAspect; import codesquad.fineants.domain.kis.client.KisCurrentPrice; import codesquad.fineants.domain.kis.repository.CurrentPriceRepository; import codesquad.fineants.domain.kis.service.KisService; @@ -111,6 +112,9 @@ class NotificationServiceTest extends AbstractContainerBaseTest { @MockBean private FirebaseMessagingService firebaseMessagingService; + @MockBean + private AccessTokenAspect accessTokenAspect; + @AfterEach void tearDown() { notificationRepository.deleteAllInBatch(); @@ -564,9 +568,9 @@ void notifyTargetPrice_whenExistNotification_thenNotSentNotification() { .hasSize(2); } - @DisplayName("종목 지정가 도달 알림을 보내는데 실패하면 알림을 저장하지 않아야 한다") + @DisplayName("종목 지정가 도달 알림을 보내는데 실패해도 알림은 저장되어야 한다") @Test - void notifyTargetPrice_whenFailSendingNotification_thenNotSaveNotification() { + void notifyTargetPrice_whenFailSendingNotification_thenSaveNotification() { // given Member member = memberRepository.save(createMember()); notificationPreferenceRepository.save(NotificationPreference.builder() @@ -591,13 +595,12 @@ void notifyTargetPrice_whenFailSendingNotification_thenNotSaveNotification() { List.of(stock.getTickerSymbol())); // then - NotificationType type = NotificationType.STOCK_TARGET_PRICE; assertThat(response.getNotifications()) .asList() - .isEmpty(); + .hasSize(1); assertThat(notificationRepository.findAllByMemberId(member.getId())) .asList() - .hasSize(0); + .hasSize(1); } @DisplayName("티커 심볼을 기준으로 종목 지정가 알림을 발송한다") diff --git a/src/test/java/codesquad/fineants/domain/portfolio_holding/service/PortfolioHoldingServiceTest.java b/src/test/java/codesquad/fineants/domain/portfolio_holding/service/PortfolioHoldingServiceTest.java index 906439cb9..9feefb7c8 100644 --- a/src/test/java/codesquad/fineants/domain/portfolio_holding/service/PortfolioHoldingServiceTest.java +++ b/src/test/java/codesquad/fineants/domain/portfolio_holding/service/PortfolioHoldingServiceTest.java @@ -24,6 +24,7 @@ import codesquad.fineants.domain.common.money.Money; import codesquad.fineants.domain.common.money.Percentage; import codesquad.fineants.domain.common.money.RateDivision; +import codesquad.fineants.domain.kis.aop.AccessTokenAspect; import codesquad.fineants.domain.kis.client.KisCurrentPrice; import codesquad.fineants.domain.kis.repository.ClosingPriceRepository; import codesquad.fineants.domain.kis.repository.CurrentPriceRepository; @@ -92,6 +93,10 @@ class PortfolioHoldingServiceTest extends AbstractContainerBaseTest { @MockBean private PortfolioHoldingEventPublisher publisher; + // CurrentPriceRepository AccessToken 모킹 + @MockBean + private AccessTokenAspect accessTokenAspect; + @AfterEach void tearDown() { purchaseHistoryRepository.deleteAllInBatch();