From ca008b86719100f0305f0d01f2135e847893cff5 Mon Sep 17 00:00:00 2001 From: LocKey Date: Sun, 30 Aug 2026 22:39:35 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EB=8F=99=EA=B8=B0=EC=8B=9D=20Mock?= =?UTF-8?q?=20Provider=20=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/provider/EmailProvider.java | 5 +++ .../notification/provider/ProviderResult.java | 6 +++ .../notification/provider/PushProvider.java | 5 +++ .../notification/provider/SmsProvider.java | 5 +++ .../provider/mock/MockEmailProvider.java | 24 +++++++++++ .../provider/mock/MockPushProvider.java | 24 +++++++++++ .../provider/mock/MockSmsProvider.java | 24 +++++++++++ .../service/NotificationService.java | 41 +++++++++++++++++++ 8 files changed, 134 insertions(+) create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/EmailProvider.java create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/ProviderResult.java create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/PushProvider.java create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/SmsProvider.java create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockEmailProvider.java create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockPushProvider.java create mode 100644 src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockSmsProvider.java diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/EmailProvider.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/EmailProvider.java new file mode 100644 index 0000000..d57d1a7 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/EmailProvider.java @@ -0,0 +1,5 @@ +package com.backendsystemdesignlab.notification.notification.provider; + +public interface EmailProvider { + ProviderResult send(String email); +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/ProviderResult.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/ProviderResult.java new file mode 100644 index 0000000..45d4544 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/ProviderResult.java @@ -0,0 +1,6 @@ +package com.backendsystemdesignlab.notification.notification.provider; + +public record ProviderResult( + boolean success +) { +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/PushProvider.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/PushProvider.java new file mode 100644 index 0000000..78c7aa3 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/PushProvider.java @@ -0,0 +1,5 @@ +package com.backendsystemdesignlab.notification.notification.provider; + +public interface PushProvider { + ProviderResult send(String deviceToken); +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/SmsProvider.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/SmsProvider.java new file mode 100644 index 0000000..6aac852 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/SmsProvider.java @@ -0,0 +1,5 @@ +package com.backendsystemdesignlab.notification.notification.provider; + +public interface SmsProvider { + ProviderResult send(String phoneNumber); +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockEmailProvider.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockEmailProvider.java new file mode 100644 index 0000000..576c3b0 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockEmailProvider.java @@ -0,0 +1,24 @@ +package com.backendsystemdesignlab.notification.notification.provider.mock; + +import com.backendsystemdesignlab.notification.notification.provider.EmailProvider; +import com.backendsystemdesignlab.notification.notification.provider.ProviderResult; +import org.springframework.stereotype.Component; + +@Component +public class MockEmailProvider implements EmailProvider { + + @Override + public ProviderResult send(String deviceToken) { + simulateDelay(); + return new ProviderResult(true); + } + + private void simulateDelay() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException(e); + } + } +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockPushProvider.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockPushProvider.java new file mode 100644 index 0000000..36bf887 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockPushProvider.java @@ -0,0 +1,24 @@ +package com.backendsystemdesignlab.notification.notification.provider.mock; + +import com.backendsystemdesignlab.notification.notification.provider.ProviderResult; +import com.backendsystemdesignlab.notification.notification.provider.PushProvider; +import org.springframework.stereotype.Component; + +@Component +public class MockPushProvider implements PushProvider { + + @Override + public ProviderResult send(String deviceToken) { + simulateDelay(); + return new ProviderResult(true); + } + + private void simulateDelay() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException(e); + } + } +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockSmsProvider.java b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockSmsProvider.java new file mode 100644 index 0000000..c07c252 --- /dev/null +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/provider/mock/MockSmsProvider.java @@ -0,0 +1,24 @@ +package com.backendsystemdesignlab.notification.notification.provider.mock; + +import com.backendsystemdesignlab.notification.notification.provider.ProviderResult; +import com.backendsystemdesignlab.notification.notification.provider.SmsProvider; +import org.springframework.stereotype.Component; + +@Component +public class MockSmsProvider implements SmsProvider { + + @Override + public ProviderResult send(String deviceToken) { + simulateDelay(); + return new ProviderResult(true); + } + + private void simulateDelay() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException(e); + } + } +} diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/service/NotificationService.java b/src/main/java/com/backendsystemdesignlab/notification/notification/service/NotificationService.java index b40d91f..e73acea 100644 --- a/src/main/java/com/backendsystemdesignlab/notification/notification/service/NotificationService.java +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/service/NotificationService.java @@ -1,9 +1,14 @@ package com.backendsystemdesignlab.notification.notification.service; +import com.backendsystemdesignlab.notification.notification.domain.DeliveryStatus; import com.backendsystemdesignlab.notification.notification.domain.Notification; import com.backendsystemdesignlab.notification.notification.domain.NotificationDelivery; import com.backendsystemdesignlab.notification.notification.dto.SendNotificationRequest; import com.backendsystemdesignlab.notification.notification.dto.SendNotificationResponse; +import com.backendsystemdesignlab.notification.notification.provider.EmailProvider; +import com.backendsystemdesignlab.notification.notification.provider.ProviderResult; +import com.backendsystemdesignlab.notification.notification.provider.PushProvider; +import com.backendsystemdesignlab.notification.notification.provider.SmsProvider; import com.backendsystemdesignlab.notification.notification.repository.NotificationDeliveryRepository; import com.backendsystemdesignlab.notification.notification.repository.NotificationRepository; import com.backendsystemdesignlab.notification.user.domain.NotificationChannel; @@ -31,6 +36,10 @@ public class NotificationService { private final NotificationPreferenceRepository preferenceRepository; private final NotificationRepository notificationRepository; private final NotificationDeliveryRepository deliveryRepository; + private final PushProvider pushProvider; + private final SmsProvider smsProvider; + private final EmailProvider emailProvider; + @Transactional public SendNotificationResponse send(SendNotificationRequest request) { @@ -89,6 +98,19 @@ public SendNotificationResponse send(SendNotificationRequest request) { deliveryRepository.saveAll(deliveries); + notification.startProcessing(); + + sendDeliveries(deliveries); + + boolean allSucceeded = deliveries.stream() + .allMatch(delivery -> delivery.getStatus() == DeliveryStatus.SENT); + + if (allSucceeded) { + notification.complete(); + } else { + notification.fail(); + } + return new SendNotificationResponse( notification.getId(), notification.getStatus(), @@ -96,6 +118,25 @@ public SendNotificationResponse send(SendNotificationRequest request) { ); } + private void sendDeliveries(List deliveries) { + + for (NotificationDelivery delivery : deliveries) { + delivery.recordAttempt(); + + ProviderResult result = switch (delivery.getChannel()) { + case PUSH -> pushProvider.send(delivery.getDestination()); + case SMS -> smsProvider.send(delivery.getDestination()); + case EMAIL -> emailProvider.send(delivery.getDestination()); + }; + + if (result.success()) { + delivery.markSent(); + } else { + delivery.markFailed(); + } + } + } + private void createPushDeliveries(User user, Notification notification, List deliveries) { List devices = userDeviceRepository.findAllByUserIdAndActiveTrue(user.getId()); From 0288ee3f8a0def978f23b134b9b70a78f2d821c4 Mon Sep 17 00:00:00 2001 From: LocKey Date: Sun, 30 Aug 2026 23:14:32 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EB=8F=99=EA=B8=B0=EC=8B=9D=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20API=20=EC=9D=91=EB=8B=B5=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/controller/NotificationController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/backendsystemdesignlab/notification/notification/controller/NotificationController.java b/src/main/java/com/backendsystemdesignlab/notification/notification/controller/NotificationController.java index 6fa4fcc..5f14af9 100644 --- a/src/main/java/com/backendsystemdesignlab/notification/notification/controller/NotificationController.java +++ b/src/main/java/com/backendsystemdesignlab/notification/notification/controller/NotificationController.java @@ -21,7 +21,7 @@ public class NotificationController { @PostMapping public ResponseEntity send(@Valid @RequestBody SendNotificationRequest request) { SendNotificationResponse response = notificationService.send(request); - return ResponseEntity.accepted().body(response); // 아직 실제 전송이 완료된 게 아니라 요청 접수 단계 (202 Accepted) + return ResponseEntity.ok(response); } }