Skip to content

Commit

Permalink
Merge pull request #314 from depromeet/refactor/#313-noti-constant
Browse files Browse the repository at this point in the history
  • Loading branch information
char-yb authored Oct 18, 2024
2 parents 02201d1 + d70bc2e commit 43946a0
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.depromeet.stonebed.domain.fcm.application;

import static com.depromeet.stonebed.global.common.constants.NotificationConstants.*;

import com.depromeet.stonebed.domain.fcm.dao.FcmNotificationRepository;
import com.depromeet.stonebed.domain.fcm.dao.FcmTokenRepository;
import com.depromeet.stonebed.domain.fcm.domain.FcmMessage;
Expand All @@ -19,7 +21,6 @@
import com.depromeet.stonebed.global.error.exception.CustomException;
import com.depromeet.stonebed.global.util.MemberUtil;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -48,14 +49,6 @@ public class FcmNotificationService {
private final MemberRepository memberRepository;
private final MemberUtil memberUtil;

private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

private static final long FIRST_BOOST_THRESHOLD = 1;
private static final long POPULAR_THRESHOLD = 1000;
private static final long SUPER_POPULAR_THRESHOLD = 5000;
private static final int BATCH_SIZE = 10;

public void saveNotification(
FcmNotificationType type,
String title,
Expand All @@ -79,18 +72,14 @@ public void saveNotification(
public FcmNotificationResponse getNotificationsForCurrentMember(String cursor, int limit) {
Member member = memberUtil.getCurrentMember();

Pageable pageable = createPageable(limit);
Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt"));
List<FcmNotification> notifications = getNotifications(cursor, member.getId(), pageable);
List<FcmNotificationDto> notificationData = convertToNotificationDto(notifications);
String nextCursor = getNextCursor(notifications);

return FcmNotificationResponse.from(notificationData, nextCursor);
}

private Pageable createPageable(int limit) {
return PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt"));
}

private List<FcmNotificationDto> convertToNotificationDto(List<FcmNotification> notifications) {
List<Long> targetIds = notifications.stream().map(FcmNotification::getTargetId).toList();

Expand Down Expand Up @@ -298,15 +287,13 @@ public void sendAndNotifications(
private List<List<String>> createBatches(List<String> tokens) {
return IntStream.range(
0,
(tokens.size() + FcmNotificationService.BATCH_SIZE - 1)
/ FcmNotificationService.BATCH_SIZE)
(tokens.size() + SQS_BATCH_SIZE - 1)
/ SQS_BATCH_SIZE) // ceil(tokens.size() / SQS_BATCH_SIZE
.mapToObj(
i ->
tokens.subList(
i * FcmNotificationService.BATCH_SIZE,
Math.min(
tokens.size(),
(i + 1) * FcmNotificationService.BATCH_SIZE)))
i * SQS_BATCH_SIZE,
Math.min(tokens.size(), (i + 1) * SQS_BATCH_SIZE)))
.collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.depromeet.stonebed.domain.sqs.application;

import static com.depromeet.stonebed.global.common.constants.NotificationConstants.*;

import com.depromeet.stonebed.domain.fcm.dao.FcmTokenRepository;
import com.depromeet.stonebed.domain.fcm.domain.FcmMessage;
import com.depromeet.stonebed.infra.properties.SqsProperties;
Expand All @@ -24,13 +26,10 @@
@RequiredArgsConstructor
@Service
public class SqsMessageService {

private final SqsClient sqsClient;

private final SqsProperties sqsProperties;

private final ObjectMapper objectMapper;
private final FcmTokenRepository fcmTokenRepository;
private final SqsClient sqsClient;

public void sendMessage(Object message) {
try {
Expand All @@ -50,57 +49,82 @@ public void sendMessage(Object message) {

public void sendBatchMessages(
List<String> tokens, String title, String message, String deepLink) {
// SQS 메시지의 최대 전송 크기는 10개이므로 이를 고려하여 분할합니다.
int batchSize = 10;

List<String> failedTokens = new ArrayList<>();

for (int i = 0; i < tokens.size(); i += batchSize) {
List<String> batchTokens = tokens.subList(i, Math.min(i + batchSize, tokens.size()));
List<SendMessageBatchRequestEntry> entries = new ArrayList<>();

for (String token : batchTokens) {
try {
FcmMessage fcmMessage = FcmMessage.of(title, message, token, deepLink);
String messageBody = objectMapper.writeValueAsString(fcmMessage);
SendMessageBatchRequestEntry entry =
SendMessageBatchRequestEntry.builder()
.id(UUID.randomUUID().toString())
.messageBody(messageBody)
.build();
entries.add(entry);
} catch (Exception e) {
log.error("메시지 직렬화 실패: {}", e.getMessage());
}
}
// 토큰 리스트를 10개씩 분할하여 처리
for (int i = 0; i < tokens.size(); i += SQS_BATCH_SIZE) {
List<String> batchTokens =
tokens.subList(i, Math.min(i + SQS_BATCH_SIZE, tokens.size()));

List<SendMessageBatchRequestEntry> entries =
createBatchEntries(batchTokens, title, message, deepLink);

if (!entries.isEmpty()) {
SendMessageBatchRequest batchRequest =
SendMessageBatchRequest.builder()
.queueUrl(sqsProperties.queueUrl())
.entries(entries)
.build();
sendBatchRequest(entries, failedTokens);
}
}

// 실패한 토큰 삭제 처리
deleteFailedTokens(failedTokens);
}

private List<SendMessageBatchRequestEntry> createBatchEntries(
List<String> batchTokens, String title, String message, String deepLink) {

List<SendMessageBatchRequestEntry> entries = new ArrayList<>();

try {
SendMessageBatchResponse batchResponse =
sqsClient.sendMessageBatch(batchRequest);
log.info("배치 메시지 전송 응답: {}", batchResponse);
// 실패한 메시지 처리
List<BatchResultErrorEntry> failedMessages = batchResponse.failed();
for (BatchResultErrorEntry failed : failedMessages) {
log.error("메시지 전송 실패, ID {}: {}", failed.id(), failed.message());
failedTokens.add(failed.id());
}

// 실패한 토큰 삭제
for (String failedToken : failedTokens) {
fcmTokenRepository.deleteByToken(failedToken);
log.info("비활성화된 FCM 토큰 삭제: {}", failedToken);
}

} catch (Exception e) {
log.error("SQS 배치 메시지 전송 실패: {}", e.getMessage());
}
for (String token : batchTokens) {
try {
FcmMessage fcmMessage = FcmMessage.of(title, message, token, deepLink);
String messageBody = objectMapper.writeValueAsString(fcmMessage);
SendMessageBatchRequestEntry entry =
SendMessageBatchRequestEntry.builder()
.id(UUID.randomUUID().toString())
.messageBody(messageBody)
.build();
entries.add(entry);
} catch (Exception e) {
log.error("메시지 직렬화 실패: {}", e.getMessage());
}
}

return entries;
}

private void sendBatchRequest(
List<SendMessageBatchRequestEntry> entries, List<String> failedTokens) {
SendMessageBatchRequest batchRequest =
SendMessageBatchRequest.builder()
.queueUrl(sqsProperties.queueUrl())
.entries(entries)
.build();

try {
SendMessageBatchResponse batchResponse = sqsClient.sendMessageBatch(batchRequest);
log.info("배치 메시지 전송 응답: {}", batchResponse);

// 실패한 메시지 처리
handleFailedMessages(batchResponse, failedTokens);

} catch (Exception e) {
log.error("SQS 배치 메시지 전송 실패: {}", e.getMessage());
}
}

private void handleFailedMessages(
SendMessageBatchResponse batchResponse, List<String> failedTokens) {
List<BatchResultErrorEntry> failedMessages = batchResponse.failed();
for (BatchResultErrorEntry failed : failedMessages) {
log.error("메시지 전송 실패, ID {}: {}", failed.id(), failed.message());
failedTokens.add(failed.id());
}
}

private void deleteFailedTokens(List<String> failedTokens) {
for (String failedToken : failedTokens) {
fcmTokenRepository.deleteByToken(failedToken);
log.info("비활성화된 FCM 토큰 삭제: {}", failedToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.depromeet.stonebed.global.common.constants;

import java.time.format.DateTimeFormatter;

public final class NotificationConstants {
public static final int SQS_BATCH_SIZE = 10;
public static final long FIRST_BOOST_THRESHOLD = 1;
public static final long POPULAR_THRESHOLD = 1000;
public static final long SUPER_POPULAR_THRESHOLD = 5000;
public static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
}

0 comments on commit 43946a0

Please sign in to comment.