From 06fe3ae7f500fb2a4b5bee9210e873eb07199e33 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 17:15:27 +0900 Subject: [PATCH 01/22] =?UTF-8?q?feat:=20Swagger=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=BB=AC,=20=EC=9A=B4=EC=98=81=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EB=AA=A8=EB=91=90=EC=97=90=20=EC=9A=94=EC=B2=AD=20=EB=B3=B4?= =?UTF-8?q?=EB=82=BC=20=EC=88=98=20=EC=9E=88=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/devkor/ontime_back/config/SchedulerConfig.java | 4 ++++ .../main/java/devkor/ontime_back/config/SwaggerConfig.java | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java diff --git a/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java b/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java new file mode 100644 index 0000000..e72b949 --- /dev/null +++ b/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java @@ -0,0 +1,4 @@ +package devkor.ontime_back.config; + +public class SchedulerConfig { +} diff --git a/ontime-back/src/main/java/devkor/ontime_back/config/SwaggerConfig.java b/ontime-back/src/main/java/devkor/ontime_back/config/SwaggerConfig.java index 002969b..54f58a8 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/config/SwaggerConfig.java +++ b/ontime-back/src/main/java/devkor/ontime_back/config/SwaggerConfig.java @@ -15,7 +15,8 @@ @Configuration @OpenAPIDefinition( servers = { - @Server(url = "https://ontime.devkor.club", description = "Production Server") + @Server(url = "https://ontime.devkor.club", description = "Production Server"), + @Server(url = "http://localhost:8080", description = "Local Serever") } ) public class SwaggerConfig { From 35bef8180d0d0f79fef9fc9414e21159f34cd556 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 17:16:20 +0900 Subject: [PATCH 02/22] =?UTF-8?q?feat:=20ScheduleConfig=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=83=9D=EC=84=B1(TaskScheduler=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ontime_back/config/SchedulerConfig.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java b/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java index e72b949..37795e2 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java +++ b/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java @@ -1,4 +1,19 @@ package devkor.ontime_back.config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +@Configuration public class SchedulerConfig { -} + + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(10); + scheduler.setThreadNamePrefix("scheduler-"); + scheduler.initialize(); + return scheduler; + } +} \ No newline at end of file From 2f156fc0cba939a22d158730c5e90b38c40bca88 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 17:16:54 +0900 Subject: [PATCH 03/22] =?UTF-8?q?feat:=20=EC=95=BD=EC=86=8D=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=20=EB=8F=99=EC=A0=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A4=84=EB=A7=81=20=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scheduler/NotificationScheduler.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java b/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java index 6c46be1..04221e7 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java +++ b/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java @@ -49,23 +49,23 @@ public void sendMorningReminder() { notificationService.sendReminder(schedulesForToday, "오늘 예정된 약속이 있습니다."); } - @Scheduled(cron = "0 * * * * *") // 매 분의 0초에 실행 - public void sendFiveMinutesBeforeReminder() { - LocalDateTime baseTime = LocalDateTime.now().plusMinutes(5); // 현재 시간 - LocalDateTime startTime = baseTime.withSecond(0).withNano(0); // 초와 나노초 제거 (분 단위로 설정) - LocalDateTime endTime = startTime.plusMinutes(1).minusNanos(1); // 다음 분의 직전까지 - - System.out.println("5분 후 시간: " + baseTime); - - // 5분 후의 scheduleTime과 일치하는 약속 조회 - List schedulesStartingSoon = scheduleRepository.findSchedulesBetween(startTime, endTime); - - for(Schedule schedule : schedulesStartingSoon) { - System.out.println("5분 뒤의 약속: " + schedule.getScheduleName()); - } - - // 알림 전송 - notificationService.sendReminder(schedulesStartingSoon, "약속 5분 전입니다. 준비하세요."); - } +// @Scheduled(cron = "0 * * * * *") // 매 분의 0초에 실행 +// public void sendFiveMinutesBeforeReminder() { +// LocalDateTime baseTime = LocalDateTime.now().plusMinutes(5); // 현재 시간 +// LocalDateTime startTime = baseTime.withSecond(0).withNano(0); // 초와 나노초 제거 (분 단위로 설정) +// LocalDateTime endTime = startTime.plusMinutes(1).minusNanos(1); // 다음 분의 직전까지 +// +// System.out.println("5분 후 시간: " + baseTime); +// +// // 5분 후의 scheduleTime과 일치하는 약속 조회 +// List schedulesStartingSoon = scheduleRepository.findSchedulesBetween(startTime, endTime); +// +// for(Schedule schedule : schedulesStartingSoon) { +// System.out.println("5분 뒤의 약속: " + schedule.getScheduleName()); +// } +// +// // 알림 전송 +// notificationService.sendReminder(schedulesStartingSoon, "약속 5분 전입니다. 준비하세요."); +// } } From 08b743241cbc448752af3997a2b4b9438d98c768 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 17:17:32 +0900 Subject: [PATCH 04/22] =?UTF-8?q?feat:=20=EC=95=BD=EC=86=8D=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20=EB=8F=99=EC=A0=81=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=EB=A7=81=ED=95=98=EB=8A=94=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=98=B8=EC=B6=9C=ED=95=98=EB=8F=84=EB=A1=9D=20Cre?= =?UTF-8?q?ate=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/devkor/ontime_back/service/ScheduleService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index 3f46c28..2a55c1f 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -26,6 +26,7 @@ public class ScheduleService { private final UserService userService; + private final NotificationService notificationService; private final ScheduleRepository scheduleRepository; private final UserRepository userRepository; @@ -128,6 +129,8 @@ public void addSchedule(ScheduleAddDto scheduleAddDto, Long userId) { .build(); scheduleRepository.save(schedule); + + notificationService.scheduleReminder(schedule); } // 지각 히스토리 반환 From c007bb5c6c9d0c3c74aec2359c194bd00fe32c43 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 17:23:14 +0900 Subject: [PATCH 05/22] =?UTF-8?q?feat:=20NotificationSchedule=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/NotificationSchedule.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java diff --git a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java new file mode 100644 index 0000000..3bdceed --- /dev/null +++ b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java @@ -0,0 +1,34 @@ +package devkor.ontime_back.entity; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class NotificationSchedule { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private LocalDateTime notificationTime; + + private Boolean isSent; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "schedule_id") + private Schedule schedule; + + @Builder + public NotificationSchedule(LocalDateTime notificationTime, Boolean isSent, Schedule schedule) { + this.notificationTime = notificationTime; + this.isSent = isSent; + this.schedule = schedule; + } +} From d31925a5dab9352724e4db1f5b59c636b770cb38 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:35:10 +0900 Subject: [PATCH 06/22] =?UTF-8?q?feat:=20NotificationSchedule=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=8A=A4=EC=BC=80=EC=A4=84=EB=A7=81=20=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/dataSources.xml | 19 +++++++ .idea/modules/devkor.ontime-back.main.iml | 8 +++ .idea/modules/ontime-back.main.iml | 7 +++ .idea/sqlDataSources.xml | 8 +++ .../NotificationScheduleRepository.java | 4 ++ .../service/NotificationRecoveryService.java | 4 ++ .../service/NotificationService.java | 52 +++++++++++++++++-- 7 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 .idea/dataSources.xml create mode 100644 .idea/modules/devkor.ontime-back.main.iml create mode 100644 .idea/modules/ontime-back.main.iml create mode 100644 .idea/sqlDataSources.xml create mode 100644 ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java create mode 100644 ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..6faad9e --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,19 @@ + + + + + mysql.8 + true + true + $PROJECT_DIR$/ontime-back/src/main/resources/application.properties + com.mysql.cj.jdbc.Driver + jdbc:mysql://localhost:3306/ontime + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/modules/devkor.ontime-back.main.iml b/.idea/modules/devkor.ontime-back.main.iml new file mode 100644 index 0000000..2b3b8af --- /dev/null +++ b/.idea/modules/devkor.ontime-back.main.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/ontime-back.main.iml b/.idea/modules/ontime-back.main.iml new file mode 100644 index 0000000..f4cd67e --- /dev/null +++ b/.idea/modules/ontime-back.main.iml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/sqlDataSources.xml b/.idea/sqlDataSources.xml new file mode 100644 index 0000000..f87c123 --- /dev/null +++ b/.idea/sqlDataSources.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java new file mode 100644 index 0000000..8ce8832 --- /dev/null +++ b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java @@ -0,0 +1,4 @@ +package devkor.ontime_back.repository; + +public class NotificationScheduleRepository { +} diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java new file mode 100644 index 0000000..22de5df --- /dev/null +++ b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java @@ -0,0 +1,4 @@ +package devkor.ontime_back.service; + +public class NotificationRecoveryService { +} diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java index 65b1292..c953883 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java @@ -2,22 +2,65 @@ import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.Message; +import devkor.ontime_back.entity.NotificationSchedule; import devkor.ontime_back.entity.Schedule; import devkor.ontime_back.entity.User; import devkor.ontime_back.entity.UserSetting; +import devkor.ontime_back.repository.NotificationScheduleRepository; import devkor.ontime_back.repository.UserSettingRepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; import java.util.List; +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class NotificationService { private final UserSettingRepository userSettingRepository; + private final TaskScheduler taskScheduler; + private final NotificationScheduleRepository notificationScheduleRepository; + + public void scheduleReminder(NotificationSchedule notificationSchedule) { + LocalDateTime reminderTime = notificationSchedule.getNotificationTime(); + + if (reminderTime.isBefore(LocalDateTime.now())) { + log.warn("약속 알림 시간이 과거인 경우 알림 스케줄링하지 않습니다. {} ({})", notificationSchedule.getSchedule().getScheduleName(), reminderTime); + return; + } + + taskScheduler.schedule( + () -> { + sendReminder(notificationSchedule, "약속 5분 전 입니다"); + }, + Date.from(reminderTime.atZone(ZoneId.systemDefault()).toInstant()) + ); + log.info("스케줄 등록 완료 {} ({})", notificationSchedule.getSchedule().getScheduleName(), reminderTime); + } + + @Transactional + public void sendReminder(NotificationSchedule notificationSchedule, String message) { + Long userId = notificationSchedule.getSchedule().getUser().getId(); + + if (userId != null) { + UserSetting userSetting = userSettingRepository.findByUserId(userId) + .orElseThrow(() -> new IllegalArgumentException("No UserSetting found in schedule's user"));// Repository 메서드 가정 + + if (Boolean.TRUE.equals(userSetting.getIsNotificationsEnabled())) { + sendNotificationToUser(notificationSchedule.getSchedule(), message); + notificationSchedule.changeStatusToSent(); + notificationScheduleRepository.save(notificationSchedule); + } + } + } public void sendReminder(List schedules, String message) { for (Schedule schedule : schedules) { @@ -25,11 +68,9 @@ public void sendReminder(List schedules, String message) { Long userId = user.getId(); if (userId != null) { - // UserSetting 테이블에서 해당 유저의 알림 설정 가져오기 UserSetting userSetting = userSettingRepository.findByUserId(userId) .orElseThrow(() -> new IllegalArgumentException("No UserSetting found in schedule's user"));// Repository 메서드 가정 - // 알림 설정 확인 if (userSetting != null && userSetting.getIsNotificationsEnabled()) { sendNotificationToUser(schedule, message); } @@ -37,7 +78,8 @@ public void sendReminder(List schedules, String message) { } } - private void sendNotificationToUser(Schedule schedule, String message) { + @Transactional + public void sendNotificationToUser(Schedule schedule, String message) { User user = schedule.getUser(); String firebaseToken = user.getFirebaseToken(); @@ -48,8 +90,8 @@ private void sendNotificationToUser(Schedule schedule, String message) { .build(); try { - String response = FirebaseMessaging.getInstance().send(firebaseMessage); - System.out.println("Firebase에 성공적으로 push notification 요청을 보냈으며, Firebase로부터 적절한 응답을 받았습니다 \n응답 내용:" + response); + FirebaseMessaging.getInstance().send(firebaseMessage); + log.info("Firebase에 성공적으로 push notification 요청을 보냈으며, Firebase로부터 적절한 응답을 받았습니다 \n알림 푸시한 약속:" + schedule.getScheduleName()); } catch (Exception e) { e.printStackTrace(); } From b1c5613d124a040b1639072fad1412390938f042 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:36:08 +0900 Subject: [PATCH 07/22] =?UTF-8?q?feat:=20=EC=95=BD=EC=86=8D=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20notificationSchedule=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=83=9D=EC=84=B1=ED=95=98=EA=B3=A0=20=EB=8F=99?= =?UTF-8?q?=EC=A0=81=EC=8A=A4=EC=BC=80=EC=A4=84=EB=A7=81=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devkor/ontime_back/service/ScheduleService.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index 2a55c1f..48cc3b5 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -1,6 +1,7 @@ package devkor.ontime_back.service; import devkor.ontime_back.dto.*; +import devkor.ontime_back.entity.NotificationSchedule; import devkor.ontime_back.entity.Place; import devkor.ontime_back.entity.Schedule; import devkor.ontime_back.entity.User; @@ -33,6 +34,7 @@ public class ScheduleService { private final PlaceRepository placeRepository; private final PreparationScheduleRepository preparationScheduleRepository; private final PreparationUserRepository preparationUserRepository; + private final NotificationScheduleRepository notificationScheduleRepository; // scheduleId, userId를 통한 권한 확인 private Schedule getScheduleWithAuthorization(UUID scheduleId, Long userId) { @@ -127,10 +129,16 @@ public void addSchedule(ScheduleAddDto scheduleAddDto, Long userId) { .isStarted(false) .latenessTime(-1) .build(); - scheduleRepository.save(schedule); - notificationService.scheduleReminder(schedule); + NotificationSchedule notification = NotificationSchedule.builder() + .notificationTime(schedule.getScheduleTime().minusMinutes(5)) // 차후 알림보내야하는 시각으로 수정 필요 + .isSent(false) + .schedule(schedule) + .build(); + notificationScheduleRepository.save(notification); + + notificationService.scheduleReminder(notification); } // 지각 히스토리 반환 From f08ba620464d5bb03413e14d2c80095ab586d304 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:37:04 +0900 Subject: [PATCH 08/22] =?UTF-8?q?feat:=20NotificationSchedule=EC=97=90=20i?= =?UTF-8?q?sSent=EB=A5=BC=20true=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devkor/ontime_back/entity/NotificationSchedule.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java index 3bdceed..f848dac 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java +++ b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java @@ -31,4 +31,10 @@ public NotificationSchedule(LocalDateTime notificationTime, Boolean isSent, Sche this.isSent = isSent; this.schedule = schedule; } + + public void changeStatusToSent() { + if(Boolean.FALSE.equals(this.isSent)) { + this.isSent = true; + } + } } From ef875260f20fb03e669786d5887df099876b5b04 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:38:01 +0900 Subject: [PATCH 09/22] =?UTF-8?q?feat:=20WAS=20=EC=9E=AC=EC=8B=9C=EC=9E=91?= =?UTF-8?q?=EC=8B=9C=20=EB=8F=99=EC=A0=81=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=A7=81=ED=96=88=EB=8D=98=20=EC=A0=95=EB=B3=B4=20=EA=B8=B0?= =?UTF-8?q?=EC=96=B5=EB=AA=BB=ED=95=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0(=EC=96=B4=ED=94=8C=EB=A6=AC=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=8B=9C=EC=9E=91=20=EC=9D=B4=ED=9B=84=20?= =?UTF-8?q?NotificationSchedule=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=9D=BD=EC=96=B4=EC=98=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationRecoveryService.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java index 22de5df..09326c2 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationRecoveryService.java @@ -1,4 +1,36 @@ package devkor.ontime_back.service; +import devkor.ontime_back.entity.NotificationSchedule; +import devkor.ontime_back.repository.NotificationScheduleRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; + +@Slf4j +@Component +@RequiredArgsConstructor public class NotificationRecoveryService { -} + + private final NotificationScheduleRepository notificationScheduleRepository; + private final NotificationService notificationService; + + @EventListener(ApplicationReadyEvent.class) + public void recoverNotificationSchedules() { + log.info("서버 부팅 완료: 알림 스케줄 복구 시작"); + + LocalDateTime now = LocalDateTime.now(); + List pendingNotifications = notificationScheduleRepository.findAllWithScheduleAndUser(now); + + + for (NotificationSchedule notification : pendingNotifications) { + notificationService.scheduleReminder(notification); + } + + log.info("알림 스케줄 복구 완료: 복구된 알림 수 = {}", pendingNotifications.size()); + } +} \ No newline at end of file From 7382cc0b6b9c9fe896677f0b4b075fd247828b19 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:38:49 +0900 Subject: [PATCH 10/22] =?UTF-8?q?WAS=EC=9E=AC=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=EC=9D=B4=ED=9B=84=20=EC=9D=BD=EC=96=B4=EC=98=A8=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=EC=A0=95=EB=B3=B4=EC=97=90=EC=84=9C=20=EC=95=BD?= =?UTF-8?q?=EC=86=8D,=EC=9C=A0=EC=A0=80=EB=A5=BC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20LazyInitializationException=20=ED=8E=98?= =?UTF-8?q?=EC=B9=98=EC=A1=B0=EC=9D=B8=EC=9C=BC=EB=A1=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotificationScheduleRepository.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java index 8ce8832..e7d3981 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java +++ b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java @@ -1,4 +1,18 @@ package devkor.ontime_back.repository; -public class NotificationScheduleRepository { +import devkor.ontime_back.entity.NotificationSchedule; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.time.LocalDateTime; +import java.util.List; + +@Repository +public interface NotificationScheduleRepository extends JpaRepository { + @Query("SELECT n FROM NotificationSchedule n " + + "JOIN FETCH n.schedule s " + + "JOIN FETCH s.user " + + "WHERE n.notificationTime > :now AND n.isSent = false") + List findAllWithScheduleAndUser(LocalDateTime now); } From f6dfc31e2d27f512b1a7de5c08eb4314c5652445 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:39:22 +0900 Subject: [PATCH 11/22] =?UTF-8?q?=EA=B8=B0=EC=A1=B4=20@Scheduled=EC=95=A0?= =?UTF-8?q?=EB=84=88=ED=85=8C=EC=9D=B4=EC=85=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=A7=A4=EB=B6=84=EB=A7=88=EB=8B=A4=20=EC=95=BD=EC=86=8D?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=B4=EC=84=9C=20=EC=95=BD=EC=86=8D=205?= =?UTF-8?q?=EB=B6=84=EC=A0=84=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=97=90?= =?UTF-8?q?=EA=B2=8C=20=EC=95=8C=EB=A6=BC=EB=B3=B4=EB=82=B4=EB=8D=98=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scheduler/NotificationScheduler.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java b/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java index 04221e7..85e0f4f 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java +++ b/ontime-back/src/main/java/devkor/ontime_back/scheduler/NotificationScheduler.java @@ -48,24 +48,5 @@ public void sendMorningReminder() { List schedulesForToday = scheduleRepository.findSchedulesBetween(startOfToday, endOfToday); notificationService.sendReminder(schedulesForToday, "오늘 예정된 약속이 있습니다."); } - -// @Scheduled(cron = "0 * * * * *") // 매 분의 0초에 실행 -// public void sendFiveMinutesBeforeReminder() { -// LocalDateTime baseTime = LocalDateTime.now().plusMinutes(5); // 현재 시간 -// LocalDateTime startTime = baseTime.withSecond(0).withNano(0); // 초와 나노초 제거 (분 단위로 설정) -// LocalDateTime endTime = startTime.plusMinutes(1).minusNanos(1); // 다음 분의 직전까지 -// -// System.out.println("5분 후 시간: " + baseTime); -// -// // 5분 후의 scheduleTime과 일치하는 약속 조회 -// List schedulesStartingSoon = scheduleRepository.findSchedulesBetween(startTime, endTime); -// -// for(Schedule schedule : schedulesStartingSoon) { -// System.out.println("5분 뒤의 약속: " + schedule.getScheduleName()); -// } -// -// // 알림 전송 -// notificationService.sendReminder(schedulesStartingSoon, "약속 5분 전입니다. 준비하세요."); -// } } From d7aadef94bba1fdd74a2444b18bee8ae046cff40 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 18:55:50 +0900 Subject: [PATCH 12/22] =?UTF-8?q?feat:=20=EB=8F=99=EC=A0=81=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=80=EC=A4=84=EB=A7=81=EB=90=9C=20=EC=95=BD=EC=86=8D?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=B7=A8=EC=86=8C=EA=B0=80=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=98=EA=B2=8C=20=ED=95=98=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=20map=EC=9E=90=EB=A3=8C=ED=98=95=EC=97=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EB=B0=8F=20=EC=95=8C=EB=A6=BC=20=EC=B7=A8=EC=86=8C?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/NotificationService.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java index c953883..97bf086 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java @@ -18,6 +18,8 @@ import java.time.ZoneId; import java.util.Date; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; @Slf4j @Service @@ -28,6 +30,7 @@ public class NotificationService { private final UserSettingRepository userSettingRepository; private final TaskScheduler taskScheduler; private final NotificationScheduleRepository notificationScheduleRepository; + private final ConcurrentHashMap> scheduledTasks = new ConcurrentHashMap<>(); public void scheduleReminder(NotificationSchedule notificationSchedule) { LocalDateTime reminderTime = notificationSchedule.getNotificationTime(); @@ -37,15 +40,25 @@ public void scheduleReminder(NotificationSchedule notificationSchedule) { return; } - taskScheduler.schedule( - () -> { - sendReminder(notificationSchedule, "약속 5분 전 입니다"); - }, + ScheduledFuture future = taskScheduler.schedule( + () -> sendReminder(notificationSchedule, "약속 5분 전입니다"), Date.from(reminderTime.atZone(ZoneId.systemDefault()).toInstant()) ); + + scheduledTasks.put(notificationSchedule.getId(), future); + log.info("스케줄 등록 완료 {} ({})", notificationSchedule.getSchedule().getScheduleName(), reminderTime); } + public void cancelScheduledNotification(Long notificationId) { + ScheduledFuture future = scheduledTasks.get(notificationId); + if (future != null && !future.isCancelled()) { + future.cancel(true); + scheduledTasks.remove(notificationId); + log.info("스케줄 취소 완료: notificationId={}", notificationId); + } + } + @Transactional public void sendReminder(NotificationSchedule notificationSchedule, String message) { Long userId = notificationSchedule.getSchedule().getUser().getId(); From a6ec8ccae9ae47a20896cc9121ef243ab91af918 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:11:43 +0900 Subject: [PATCH 13/22] =?UTF-8?q?feat:=20=EC=95=BD=EC=86=8D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95/=EC=82=AD=EC=A0=9C=EC=8B=9C=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A4=84=EB=A7=81=EB=90=90=EB=8D=98=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=B7=A8=EC=86=8C=EB=90=98=EA=B2=8C=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 --- .../entity/NotificationSchedule.java | 8 +++++++ .../NotificationScheduleRepository.java | 4 ++++ .../ontime_back/response/ErrorCode.java | 4 ++-- .../ontime_back/service/ScheduleService.java | 24 +++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java index f848dac..a54fa24 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java +++ b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java @@ -37,4 +37,12 @@ public void changeStatusToSent() { this.isSent = true; } } + + public void updateNotificationTime(LocalDateTime localDateTime) { + this.notificationTime = localDateTime; + } + + public void markAsUnsent() { + this.isSent = false; + } } diff --git a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java index e7d3981..2030b9f 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java +++ b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java @@ -7,6 +7,8 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; +import java.util.UUID; @Repository public interface NotificationScheduleRepository extends JpaRepository { @@ -15,4 +17,6 @@ public interface NotificationScheduleRepository extends JpaRepository :now AND n.isSent = false") List findAllWithScheduleAndUser(LocalDateTime now); + + Optional findByScheduleId(UUID scheduleId); } diff --git a/ontime-back/src/main/java/devkor/ontime_back/response/ErrorCode.java b/ontime-back/src/main/java/devkor/ontime_back/response/ErrorCode.java index fd30c82..fbd8a5c 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/response/ErrorCode.java +++ b/ontime-back/src/main/java/devkor/ontime_back/response/ErrorCode.java @@ -28,10 +28,10 @@ public enum ErrorCode { SCHEDULE_NOT_FOUND("1010", "해당 약속이 존재하지 않습니다.", HttpStatus.BAD_REQUEST), FIREBASE("1011", "FIREBASE로 메세지를 발송하였으나 오류가 발생했습니다.(유효하지 않은 토큰 등)", HttpStatus.BAD_REQUEST), FIRST_PREPARATION_NOT_FOUND("1012", "해당 ID의 사용자의 준비과정을 찾을 수 없습니다.", HttpStatus.BAD_REQUEST), - + NOTIFICATION_NOT_FOUND("1013", "알림을 찾을 수 없습니다.", HttpStatus.BAD_REQUEST ), // 공통 오류 메시지 - UNEXPECTED_ERROR("1000", "Unexpected Error: An unexpected error occurred.", HttpStatus.INTERNAL_SERVER_ERROR); + UNEXPECTED_ERROR("1000", "Unexpected Error: An unexpected error occurred.", HttpStatus.INTERNAL_SERVER_ERROR),; private final String code; private final String message; diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index 48cc3b5..4e84ef0 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -85,11 +85,20 @@ public ScheduleDto showScheduleByScheduleId(Long userId, UUID scheduleId) { @Transactional public void deleteSchedule(UUID scheduleId, Long userId) { Schedule schedule = getScheduleWithAuthorization(scheduleId, userId); + NotificationSchedule notification = notificationScheduleRepository.findByScheduleId(scheduleId) + .orElseThrow(() -> new GeneralException(NOTIFICATION_NOT_FOUND)); + + cancleAndDeleteNotification(notification); preparationScheduleRepository.deleteBySchedule(schedule); scheduleRepository.deleteByScheduleId(scheduleId); } + private void cancleAndDeleteNotification(NotificationSchedule notification) { + notificationService.cancelScheduledNotification(notification.getId()); + notificationScheduleRepository.delete(notification); + } + // schedule 수정 @Transactional public void modifySchedule(Long userId, UUID scheduleId, ScheduleModDto scheduleModDto) { @@ -106,6 +115,21 @@ public void modifySchedule(Long userId, UUID scheduleId, ScheduleModDto schedule scheduleModDto.getScheduleSpareTime(), scheduleModDto.getLatenessTime(), scheduleModDto.getScheduleNote()); + scheduleRepository.save(schedule); + + + NotificationSchedule notification = notificationScheduleRepository.findByScheduleId(scheduleId) + .orElseThrow(() -> new GeneralException(NOTIFICATION_NOT_FOUND)); + + updateAndRescheduleNotification(scheduleModDto, notification); + } + + private void updateAndRescheduleNotification(ScheduleModDto scheduleModDto, NotificationSchedule notification) { + notificationService.cancelScheduledNotification(notification.getId()); + notification.updateNotificationTime(scheduleModDto.getScheduleTime().minusMinutes(5)); + notification.markAsUnsent(); + notificationScheduleRepository.save(notification); + notificationService.scheduleReminder(notification); } // schedule 추가 From 66a0f1c4fe02c2e928f2424bb46eafe9f28e1fcc Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:16:57 +0900 Subject: [PATCH 14/22] =?UTF-8?q?fix:=20=EC=8A=A4=EC=BC=80=EC=A4=84ID?= =?UTF-8?q?=EB=B0=94=ED=83=95=EC=9C=BC=EB=A1=9C=20notification=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=9D=98=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/NotificationScheduleRepository.java | 2 +- .../main/java/devkor/ontime_back/service/ScheduleService.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java index 2030b9f..0e88702 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java +++ b/ontime-back/src/main/java/devkor/ontime_back/repository/NotificationScheduleRepository.java @@ -18,5 +18,5 @@ public interface NotificationScheduleRepository extends JpaRepository :now AND n.isSent = false") List findAllWithScheduleAndUser(LocalDateTime now); - Optional findByScheduleId(UUID scheduleId); + Optional findByScheduleScheduleId(UUID scheduleId); } diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index 4e84ef0..e43a130 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -85,7 +85,7 @@ public ScheduleDto showScheduleByScheduleId(Long userId, UUID scheduleId) { @Transactional public void deleteSchedule(UUID scheduleId, Long userId) { Schedule schedule = getScheduleWithAuthorization(scheduleId, userId); - NotificationSchedule notification = notificationScheduleRepository.findByScheduleId(scheduleId) + NotificationSchedule notification = notificationScheduleRepository.findByScheduleScheduleId(scheduleId) .orElseThrow(() -> new GeneralException(NOTIFICATION_NOT_FOUND)); cancleAndDeleteNotification(notification); @@ -118,7 +118,7 @@ public void modifySchedule(Long userId, UUID scheduleId, ScheduleModDto schedule scheduleRepository.save(schedule); - NotificationSchedule notification = notificationScheduleRepository.findByScheduleId(scheduleId) + NotificationSchedule notification = notificationScheduleRepository.findByScheduleScheduleId(scheduleId) .orElseThrow(() -> new GeneralException(NOTIFICATION_NOT_FOUND)); updateAndRescheduleNotification(scheduleModDto, notification); From 0d961dfd39b72b1b4032e8d882c8d0d666175c59 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:21:07 +0900 Subject: [PATCH 15/22] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EC=95=8C=EB=A6=BC=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8/=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A4=84=ED=95=98=EB=8A=94=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=9D=98=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=8D=94=20specific=ED=95=98=EA=B2=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20for=20=ED=85=8C=EC=8A=A4=ED=8A=B8=ED=95=98=EA=B8=B0?= =?UTF-8?q?=20=EC=89=AC=EC=9A=B4=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devkor/ontime_back/service/ScheduleService.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index e43a130..f410b6f 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -97,6 +97,7 @@ public void deleteSchedule(UUID scheduleId, Long userId) { private void cancleAndDeleteNotification(NotificationSchedule notification) { notificationService.cancelScheduledNotification(notification.getId()); notificationScheduleRepository.delete(notification); + log.info("{}에 대한 알림 취소 및 삭제 됨", notification.getSchedule().getScheduleName()t); } // schedule 수정 @@ -120,16 +121,17 @@ public void modifySchedule(Long userId, UUID scheduleId, ScheduleModDto schedule NotificationSchedule notification = notificationScheduleRepository.findByScheduleScheduleId(scheduleId) .orElseThrow(() -> new GeneralException(NOTIFICATION_NOT_FOUND)); - - updateAndRescheduleNotification(scheduleModDto, notification); + LocalDateTime newNotificationTime = scheduleModDto.getScheduleTime().minusMinutes(5); + updateAndRescheduleNotification(newNotificationTime, notification); } - private void updateAndRescheduleNotification(ScheduleModDto scheduleModDto, NotificationSchedule notification) { + private void updateAndRescheduleNotification(LocalDateTime newNotificationTime, NotificationSchedule notification) { notificationService.cancelScheduledNotification(notification.getId()); - notification.updateNotificationTime(scheduleModDto.getScheduleTime().minusMinutes(5)); + notification.updateNotificationTime(newNotificationTime); notification.markAsUnsent(); notificationScheduleRepository.save(notification); notificationService.scheduleReminder(notification); + log.info("{}에 대한 알림정보 업데이트되고 스케줄링 계획도 리스케줄됨", notification.getSchedule().getScheduleName()); } // schedule 추가 From 81aa648aed4368ccd670ceed3fd0a8d9f70623da Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:23:01 +0900 Subject: [PATCH 16/22] =?UTF-8?q?chore:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(=EC=88=9C=EC=88=98=20=EC=8B=A4=EC=88=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/devkor/ontime_back/service/ScheduleService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index f410b6f..9cce5e5 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -97,7 +97,7 @@ public void deleteSchedule(UUID scheduleId, Long userId) { private void cancleAndDeleteNotification(NotificationSchedule notification) { notificationService.cancelScheduledNotification(notification.getId()); notificationScheduleRepository.delete(notification); - log.info("{}에 대한 알림 취소 및 삭제 됨", notification.getSchedule().getScheduleName()t); + log.info("{}에 대한 알림 취소 및 삭제 됨", notification.getSchedule().getScheduleName()); } // schedule 수정 From 318641371e97fe8e4883a11ed41756e11b4f89df Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:26:38 +0900 Subject: [PATCH 17/22] =?UTF-8?q?feat:=20Task=20Scheduler=20=EB=8B=A4?= =?UTF-8?q?=EC=A4=91=20=EC=8A=A4=EB=A0=88=EB=93=9C=20=EC=84=A4=EC=A0=95(?= =?UTF-8?q?=EC=9D=BC=EB=8B=A8=2020=EA=B0=9C=EB=A1=9C=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=ED=95=B4=EB=86=93=EC=9D=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/devkor/ontime_back/config/SchedulerConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java b/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java index 37795e2..924d6d1 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java +++ b/ontime-back/src/main/java/devkor/ontime_back/config/SchedulerConfig.java @@ -11,7 +11,7 @@ public class SchedulerConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); - scheduler.setPoolSize(10); + scheduler.setPoolSize(20); // 필요시 더 늘릴 수 있음 scheduler.setThreadNamePrefix("scheduler-"); scheduler.initialize(); return scheduler; From fa962c2e2f497f6600a9cb7dc7bc336c05a6d170 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:28:11 +0900 Subject: [PATCH 18/22] =?UTF-8?q?feat:=20sendReminder=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=B9=84=EB=8F=99=EA=B8=B0=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/devkor/ontime_back/service/NotificationService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java index 97bf086..db9a597 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/NotificationService.java @@ -11,6 +11,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,6 +24,7 @@ import java.util.concurrent.ScheduledFuture; @Slf4j +@EnableAsync @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -59,6 +62,7 @@ public void cancelScheduledNotification(Long notificationId) { } } + @Async @Transactional public void sendReminder(NotificationSchedule notificationSchedule, String message) { Long userId = notificationSchedule.getSchedule().getUser().getId(); From 9a1b530d4003dabc4447cf8e7baf3c26b86ee92e Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 19:38:38 +0900 Subject: [PATCH 19/22] =?UTF-8?q?fix:=20=EC=8A=A4=EC=BC=80=EC=A4=84=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20fk=EC=A0=9C?= =?UTF-8?q?=EC=95=BD=EC=A1=B0=EA=B1=B4=20=EB=95=8C=EB=AC=B8=EC=97=90=20500?= =?UTF-8?q?=EB=9C=A8=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=ED=95=B4=EA=B2=B0(?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=82=AD=EC=A0=9C=20=EC=A0=84=EC=97=90=20?= =?UTF-8?q?fk=EC=97=B0=EA=B2=B0=20=EB=81=8A=EA=B3=A0=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=ED=95=9C=20=EB=92=A4=20flush=ED=95=98=EC=97=AC=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=EB=90=98=EA=B2=8C=ED=95=98=EC=97=AC=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=ED=95=98=EC=98=80=EC=9D=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devkor/ontime_back/entity/NotificationSchedule.java | 4 ++++ .../java/devkor/ontime_back/service/ScheduleService.java | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java index a54fa24..047a841 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java +++ b/ontime-back/src/main/java/devkor/ontime_back/entity/NotificationSchedule.java @@ -45,4 +45,8 @@ public void updateNotificationTime(LocalDateTime localDateTime) { public void markAsUnsent() { this.isSent = false; } + + public void disconnectSchedule() { + this.schedule = null; + } } diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index 9cce5e5..e9fc799 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -89,15 +89,17 @@ public void deleteSchedule(UUID scheduleId, Long userId) { .orElseThrow(() -> new GeneralException(NOTIFICATION_NOT_FOUND)); cancleAndDeleteNotification(notification); - + notificationScheduleRepository.flush(); preparationScheduleRepository.deleteBySchedule(schedule); scheduleRepository.deleteByScheduleId(scheduleId); } private void cancleAndDeleteNotification(NotificationSchedule notification) { + log.info("{}에 대한 알림 취소 및 삭제 됨", notification.getSchedule().getScheduleName()); + notification.disconnectSchedule(); notificationService.cancelScheduledNotification(notification.getId()); notificationScheduleRepository.delete(notification); - log.info("{}에 대한 알림 취소 및 삭제 됨", notification.getSchedule().getScheduleName()); + log.info("알림 삭제 완료"); } // schedule 수정 From 9a5f532e85af4e0cac9de898e9d1424ff86774cf Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 20:26:45 +0900 Subject: [PATCH 20/22] =?UTF-8?q?feat:=20flyway=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A4=84=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=8C=8C=EC=9D=BC(V2)=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/migration/V2__create_notification_schedule.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 ontime-back/src/main/resources/db/migration/V2__create_notification_schedule.sql diff --git a/ontime-back/src/main/resources/db/migration/V2__create_notification_schedule.sql b/ontime-back/src/main/resources/db/migration/V2__create_notification_schedule.sql new file mode 100644 index 0000000..68bbe01 --- /dev/null +++ b/ontime-back/src/main/resources/db/migration/V2__create_notification_schedule.sql @@ -0,0 +1,10 @@ +CREATE TABLE notification_schedule ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + notification_time TIMESTAMP, + is_sent BOOLEAN, + schedule_id BINARY(16), + CONSTRAINT fk_notification_schedule_schedule + FOREIGN KEY (schedule_id) + REFERENCES schedule (schedule_id) + ON DELETE CASCADE +); \ No newline at end of file From d64112f74f2e344f5fad5bdbc7395c2c29e68d50 Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Sun, 27 Apr 2025 20:27:15 +0900 Subject: [PATCH 21/22] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EB=8F=99=EB=90=98=EA=B2=8C=20not?= =?UTF-8?q?ificationSchedule=EB=8D=B0=EC=9D=B4=ED=84=B0=EA=B0=80=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B3=B3=EC=97=90=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ScheduleServiceTest.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ontime-back/src/test/java/devkor/ontime_back/service/ScheduleServiceTest.java b/ontime-back/src/test/java/devkor/ontime_back/service/ScheduleServiceTest.java index 694482c..9b1887e 100644 --- a/ontime-back/src/test/java/devkor/ontime_back/service/ScheduleServiceTest.java +++ b/ontime-back/src/test/java/devkor/ontime_back/service/ScheduleServiceTest.java @@ -47,6 +47,8 @@ class ScheduleServiceTest { @Autowired private PasswordEncoder passwordEncoder; + @Autowired + private NotificationScheduleRepository notificationScheduleRepository; @AfterEach void tearDown() { @@ -647,8 +649,13 @@ void deleteSchedule_success() { .place(place1) .user(newUser) .build(); - + NotificationSchedule notificationSchedule = NotificationSchedule.builder() + .notificationTime(LocalDateTime.of(2025, 2, 23, 6, 55)) + .isSent(false) + .schedule(addedSchedule1) + .build(); scheduleRepository.save(addedSchedule1); + notificationScheduleRepository.save(notificationSchedule); // when scheduleService.deleteSchedule(addedSchedule1.getScheduleId(), newUser.getId()); @@ -799,6 +806,12 @@ void modifySchedule_success() { .scheduleSpareTime(5) .latenessTime(10) .build(); + NotificationSchedule notificationSchedule = NotificationSchedule.builder() + .notificationTime(LocalDateTime.of(2025, 2, 23, 6, 55)) + .isSent(false) + .schedule(addedSchedule1) + .build(); + notificationScheduleRepository.save(notificationSchedule); // when scheduleService.modifySchedule(newUser.getId(), addedSchedule1.getScheduleId(), scheduleModDto); @@ -859,6 +872,12 @@ void modifySchedule_withNewPlace() { .scheduleSpareTime(5) .latenessTime(10) .build(); + NotificationSchedule notificationSchedule = NotificationSchedule.builder() + .notificationTime(LocalDateTime.of(2025, 2, 23, 6, 55)) + .isSent(false) + .schedule(addedSchedule1) + .build(); + notificationScheduleRepository.save(notificationSchedule); // when scheduleService.modifySchedule(newUser.getId(), scheduleId, scheduleModDto); From faaace61f8855e0367acaa07ec3bba9c19f50adf Mon Sep 17 00:00:00 2001 From: JunbeomKoreaUniv Date: Tue, 29 Apr 2025 08:40:09 +0900 Subject: [PATCH 22/22] =?UTF-8?q?feat:=20=EC=95=BD=EC=86=8D=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=EC=9D=B4=20=EB=B3=80=EA=B2=BD=EB=90=90=EC=9D=84=20?= =?UTF-8?q?=EB=95=8C=EB=A7=8C=20=EC=95=8C=EB=A6=BC=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=EC=9D=84=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/devkor/ontime_back/service/ScheduleService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java index e9fc799..e93e8ea 100644 --- a/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java +++ b/ontime-back/src/main/java/devkor/ontime_back/service/ScheduleService.java @@ -128,6 +128,8 @@ public void modifySchedule(Long userId, UUID scheduleId, ScheduleModDto schedule } private void updateAndRescheduleNotification(LocalDateTime newNotificationTime, NotificationSchedule notification) { + if(newNotificationTime == notification.getNotificationTime()) return; + notificationService.cancelScheduledNotification(notification.getId()); notification.updateNotificationTime(newNotificationTime); notification.markAsUnsent();