Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package in.koreatech.koin.domain.notification.repository;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import in.koreatech.koin.domain.notification.model.Notification;
import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class NotificationJdbcRepository {

private static final int BATCH_SIZE = 1_000;

private final JdbcTemplate jdbcTemplate;

public void batchInsert(List<Notification> notifications) {
if (notifications.isEmpty()) {
return;
}

String sql = """
INSERT INTO notification (
app_path,
scheme_uri,
title,
message,
image_url,
type,
users_id,
is_read,
created_at,
updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""";

LocalDateTime now = LocalDateTime.now();

jdbcTemplate.batchUpdate(
sql,
notifications,
BATCH_SIZE,
(preparedStatement, notification) -> {
preparedStatement.setString(1, notification.getMobileAppPath().name());
preparedStatement.setString(2, notification.getSchemeUri());
preparedStatement.setString(3, notification.getTitle());
preparedStatement.setString(4, notification.getMessage());
preparedStatement.setString(5, notification.getImageUrl());
preparedStatement.setString(6, notification.getType().toUpperCase());
preparedStatement.setInt(7, notification.getUser().getId());
preparedStatement.setBoolean(8, notification.isRead());
preparedStatement.setObject(9, now);
preparedStatement.setObject(10, now);
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import in.koreatech.koin.domain.notification.model.NotificationDetailSubscribeType;
import in.koreatech.koin.domain.notification.model.NotificationSubscribe;
import in.koreatech.koin.domain.notification.model.NotificationSubscribeType;
import in.koreatech.koin.domain.notification.repository.NotificationRepository;
import in.koreatech.koin.domain.notification.repository.NotificationJdbcRepository;
import in.koreatech.koin.domain.notification.repository.NotificationSubscribeRepository;
import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.domain.user.repository.UserRepository;
Expand All @@ -34,18 +34,26 @@ public class NotificationService {
public record NotificationDeliveryResult(Notification notification, boolean delivered) {}

private final UserRepository userRepository;
private final NotificationRepository notificationRepository;
private final NotificationPersistenceService notificationPersistenceService;
private final FcmClient fcmClient;
private final NotificationSubscribeRepository notificationSubscribeRepository;
private final NotificationJdbcRepository notificationJdbcRepository;

@Transactional
public void pushNotifications(List<Notification> notifications) {
if (notifications.isEmpty()) {
return;
}
notificationRepository.saveAll(notifications);
runAfterCommit(() -> notifications.forEach(this::sendNotificationSafely));
notificationJdbcRepository.batchInsert(notifications);
notifications.forEach(notification -> fcmClient.sendMessage(
notification.getUser().getDeviceToken(),
notification.getTitle(),
notification.getMessage(),
notification.getImageUrl(),
notification.getMobileAppPath(),
notification.getSchemeUri(),
notification.getType().toLowerCase()
));
Comment on lines +48 to +56
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runAfterCommit(() -> notifications.forEach(this::sendNotificationSafely))로 하면, DB 커밋 실패해도 전송되는 문제를 막을 수 있습니다

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분은 NotificationService 코드 리펙토링을 별도로 진행하면서 재적용할 예정입니당

}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,21 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;

import java.util.List;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import in.koreatech.koin.domain.notification.model.Notification;
import in.koreatech.koin.domain.notification.model.NotificationFactory;
import in.koreatech.koin.domain.notification.repository.NotificationRepository;
import in.koreatech.koin.domain.notification.repository.NotificationJdbcRepository;
import in.koreatech.koin.domain.notification.repository.NotificationSubscribeRepository;
import in.koreatech.koin.domain.notification.service.NotificationPersistenceService;
import in.koreatech.koin.domain.notification.service.NotificationService;
Expand All @@ -40,9 +35,6 @@ class NotificationServiceTest {
@Mock
private UserRepository userRepository;

@Mock
private NotificationRepository notificationRepository;

@Mock
private NotificationPersistenceService notificationPersistenceService;

Expand All @@ -55,6 +47,9 @@ class NotificationServiceTest {
@Mock
private NotificationFactory notificationFactory;

@Mock
private NotificationJdbcRepository notificationJdbcRepository;

@Test
@DisplayName("알림 전송 결과 조회는 전송 성공 시에만 알림 레코드를 저장한다.")
void pushNotificationsWithResult_whenDelivered_savesNotification() {
Expand Down Expand Up @@ -137,12 +132,11 @@ void pushNotification_savesNotificationBeforeSend() {

notificationService.pushNotification(notification);

InOrder inOrder = inOrder(notificationRepository, fcmClient);
inOrder.verify(notificationRepository).saveAll(List.of(notification));
InOrder inOrder = inOrder(notificationJdbcRepository, fcmClient);
inOrder.verify(notificationJdbcRepository).batchInsert(List.of(notification));
inOrder.verify(fcmClient).sendMessage(
anyString(), anyString(), anyString(), any(), any(), anyString(), anyString()
);
verify(notificationRepository, never()).save(notification);
}

private Notification createNotification(String deviceToken) {
Expand Down
Loading