diff --git a/src/main/java/plub/plubserver/common/dummy/FeedDummy.java b/src/main/java/plub/plubserver/common/dummy/FeedDummy.java index 93c7469b..1ff255f1 100644 --- a/src/main/java/plub/plubserver/common/dummy/FeedDummy.java +++ b/src/main/java/plub/plubserver/common/dummy/FeedDummy.java @@ -4,17 +4,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; -import plub.plubserver.common.dto.CommentDto; -import plub.plubserver.domain.account.model.Account; import plub.plubserver.domain.account.service.AccountService; -import plub.plubserver.domain.feed.dto.FeedDto; import plub.plubserver.domain.feed.repository.FeedRepository; import plub.plubserver.domain.feed.service.FeedService; import javax.annotation.PostConstruct; -import static plub.plubserver.common.dummy.DummyImage.PLUB_MAIN_LOGO; - @Slf4j @Component("feedDummy") @DependsOn("plubbingDummy") @@ -26,88 +21,88 @@ public class FeedDummy { @PostConstruct public void init() { - if (feedRepository.count() > 21) { - log.info("[3] 피드가 존재하여 더미를 생성하지 않았습니다."); - return; - } - - Account admin1 = accountService.getAccountByEmail("admin1"); - Account admin2 = accountService.getAccountByEmail("admin2"); - - // 피드 더미 (plubbingId = 1) - for (int i = 1; i < 11; i++) { - FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() - .title("title" + i) - .content("줄글 내용 ~~~ 어쩌구 게시글 " + i) - .feedImage(PLUB_MAIN_LOGO) - .feedType("PHOTO_LINE") - .build(); - feedService.createFeed(1L, admin1, form); -// if (i % 4 == 0) -// feedService.pinFeed(admin1, 1L, (long) i); - } - - for (int i = 11; i < 21; i++) { - FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() - .title("title" + i) - .content("줄글만 있는 게시글 ~~~ 즐거운 플러빙 ~~~ 저쩌구 게시글 " + i) - .feedImage("") - .feedType("LINE") - .build(); - feedService.createFeed(1L, admin1, form); -// if (i % 4 == 0) -// feedService.pinFeed(admin1, 1L, (long) i); - } - - for (int i = 21; i < 31; i++) { - FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() - .title("title" + i) - .content("") - .feedImage(PLUB_MAIN_LOGO) - .feedType("PHOTO") - .build(); - feedService.createFeed(1L, admin1, form); -// if (i % 4 == 0) -// feedService.pinFeed(admin1, 1L, (long) i); - } - - for (int i = 1; i < 6; i++) { - FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() - .title(i + "번째 멤버와 함께 갑니다.") - .content("김밥먹고싶다 님이 요란한 한줄 에 들어왔어요") - .feedImage("") - .feedType("LINE") - .build(); - feedService.createFeed(1L, admin1, form); - feedService.makeSystem(30L + i); - } - - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("아자자 댓글 " + i) - .build(); - feedService.createFeedComment(admin1, 1L, 22L, form); - } - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("플러빙 댓글 " + i) - .build(); - feedService.createFeedComment(admin2, 1L, 22L, form); - } - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("대댓글 " + i) - .parentCommentId(1L) - .build(); - feedService.createFeedComment(admin1, 1L, 22L, form); - } - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("대대댓글 " + i) - .parentCommentId(15L + i) - .build(); - feedService.createFeedComment(admin1, 1L, 22L, form); - } +// if (feedRepository.count() > 21) { +// log.info("[3] 피드가 존재하여 더미를 생성하지 않았습니다."); +// return; +// } +// +// Account admin1 = accountService.getAccountByEmail("admin1"); +// Account admin2 = accountService.getAccountByEmail("admin2"); +// +// // 피드 더미 (plubbingId = 1) +// for (int i = 1; i < 11; i++) { +// FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() +// .title("title" + i) +// .content("줄글 내용 ~~~ 어쩌구 게시글 " + i) +// .feedImage(PLUB_MAIN_LOGO) +// .feedType("PHOTO_LINE") +// .build(); +// feedService.createFeed(1L, admin1, form); +//// if (i % 4 == 0) +//// feedService.pinFeed(admin1, 1L, (long) i); +// } +// +// for (int i = 11; i < 21; i++) { +// FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() +// .title("title" + i) +// .content("줄글만 있는 게시글 ~~~ 즐거운 플러빙 ~~~ 저쩌구 게시글 " + i) +// .feedImage("") +// .feedType("LINE") +// .build(); +// feedService.createFeed(1L, admin1, form); +//// if (i % 4 == 0) +//// feedService.pinFeed(admin1, 1L, (long) i); +// } +// +// for (int i = 21; i < 31; i++) { +// FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() +// .title("title" + i) +// .content("") +// .feedImage(PLUB_MAIN_LOGO) +// .feedType("PHOTO") +// .build(); +// feedService.createFeed(1L, admin1, form); +//// if (i % 4 == 0) +//// feedService.pinFeed(admin1, 1L, (long) i); +// } +// +// for (int i = 1; i < 6; i++) { +// FeedDto.CreateFeedRequest form = FeedDto.CreateFeedRequest.builder() +// .title(i + "번째 멤버와 함께 갑니다.") +// .content("김밥먹고싶다 님이 요란한 한줄 에 들어왔어요") +// .feedImage("") +// .feedType("LINE") +// .build(); +// feedService.createFeed(1L, admin1, form); +// feedService.makeSystem(30L + i); +// } +// +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("아자자 댓글 " + i) +// .build(); +// feedService.createFeedComment(admin1, 1L, 22L, form); +// } +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("플러빙 댓글 " + i) +// .build(); +// feedService.createFeedComment(admin2, 1L, 22L, form); +// } +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("대댓글 " + i) +// .parentCommentId(1L) +// .build(); +// feedService.createFeedComment(admin1, 1L, 22L, form); +// } +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("대대댓글 " + i) +// .parentCommentId(15L + i) +// .build(); +// feedService.createFeedComment(admin1, 1L, 22L, form); +// } log.info("[3] 피드 더미 생성 완료."); } diff --git a/src/main/java/plub/plubserver/common/dummy/NoticeDummy.java b/src/main/java/plub/plubserver/common/dummy/NoticeDummy.java index 07ca3bfb..4d415ecc 100644 --- a/src/main/java/plub/plubserver/common/dummy/NoticeDummy.java +++ b/src/main/java/plub/plubserver/common/dummy/NoticeDummy.java @@ -4,7 +4,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; -import plub.plubserver.common.dto.CommentDto; import plub.plubserver.domain.account.model.Account; import plub.plubserver.domain.account.service.AccountService; import plub.plubserver.domain.notice.dto.NoticeDto; @@ -30,7 +29,6 @@ public void init() { } Account admin1 = accountService.getAccountByEmail("admin1"); - System.out.println(admin1.getEmail()); Account admin2 = accountService.getAccountByEmail("admin2"); for (int i = 1; i < 40; i++) { @@ -40,33 +38,33 @@ public void init() { .build(); noticeService.createNotice(1L, admin1, form); } - - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("좋은 공지네요 " + i) - .build(); - noticeService.createNoticeComment(admin1, 1L, 1L, form); - } - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("전달 감사합니다 " + i) - .build(); - noticeService.createNoticeComment(admin2, 1L, 1L, form); - } - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("대댓글 " + i) - .parentCommentId(1L) - .build(); - noticeService.createNoticeComment(admin1, 1L, 1L, form); - } - for (int i = 0; i < 5; i++) { - CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() - .content("대대댓글 " + i) - .parentCommentId(15L + i) - .build(); - noticeService.createNoticeComment(admin2, 1L, 1L, form); - } +// +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("좋은 공지네요 " + i) +// .build(); +// noticeService.createNoticeComment(admin1, 1L, 1L, form); +// } +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("전달 감사합니다 " + i) +// .build(); +// noticeService.createNoticeComment(admin2, 1L, 1L, form); +// } +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("대댓글 " + i) +// .parentCommentId(1L) +// .build(); +// noticeService.createNoticeComment(admin1, 1L, 1L, form); +// } +// for (int i = 0; i < 5; i++) { +// CommentDto.CreateCommentRequest form = CommentDto.CreateCommentRequest.builder() +// .content("대대댓글 " + i) +// .parentCommentId(15L + i) +// .build(); +// noticeService.createNoticeComment(admin2, 1L, 1L, form); +// } log.info("[7] 공지 더미 생성 완료."); } diff --git a/src/main/java/plub/plubserver/common/dummy/PlubbingDummy.java b/src/main/java/plub/plubserver/common/dummy/PlubbingDummy.java index 9d707642..2993f474 100644 --- a/src/main/java/plub/plubserver/common/dummy/PlubbingDummy.java +++ b/src/main/java/plub/plubserver/common/dummy/PlubbingDummy.java @@ -7,10 +7,7 @@ import plub.plubserver.domain.account.model.Account; import plub.plubserver.domain.account.service.AccountService; import plub.plubserver.domain.plubbing.dto.PlubbingDto.CreatePlubbingRequest; -import plub.plubserver.domain.plubbing.model.Plubbing; import plub.plubserver.domain.plubbing.service.PlubbingService; -import plub.plubserver.domain.recruit.dto.QuestionDto.AnswerRequest; -import plub.plubserver.domain.recruit.dto.RecruitDto.ApplyRecruitRequest; import plub.plubserver.domain.recruit.repository.AppliedAccountRepository; import plub.plubserver.domain.recruit.repository.RecruitRepository; import plub.plubserver.domain.recruit.service.RecruitService; @@ -61,80 +58,80 @@ public void init() { plubbingService.createPlubbing(admin1, form); plubbingService.createPlubbing(admin2, form); } - - for (int i = 0; i < 15; i++) { - CreatePlubbingRequest form = CreatePlubbingRequest.builder() - .subCategoryIds(List.of(52L)) - .title("프로그래밍 모임" + i) - .name("코딩 모임" + i) - .goal("코틀린 마스터" + i) - .introduce("모각코해요" + i) - .mainImage(PLUB_MAIN_LOGO) - .days(List.of("SAT", "SUN")) - .onOff("ON") - .address("서울특별시 강남구 테헤란로 427") - .time("2200") - .maxAccountNum(5) - .questions(List.of("질문1", "질문2", "질문3")) - .build(); - plubbingService.createPlubbing(admin1, form); - } - - for (int i = 0; i < 5; i++) { - CreatePlubbingRequest form = CreatePlubbingRequest.builder() - .subCategoryIds(List.of(16L)) - .title("배드민턴 모임" + i) - .name("배민모임" + i) - .goal("배드민턴 스매쉬 잘 치기" + i) - .introduce("우리는 배민 이다") - .mainImage(PLUB_MAIN_LOGO) - .days(List.of("THR", "FRI", "SAT", "SUN")) - .onOff("OFF") - .roadAddress("서울특별시 강남구 테헤란로 427") - .address("서울특별시 강남구 테헤란로 333") - .placeName("강남공원") - .placePositionX(37.4981) - .placePositionY(127.02761) - .time("1700") - .maxAccountNum(5) - .questions(List.of("질문1", "질문2", "질문3")) - .build(); - plubbingService.createPlubbing(admin1, form); - } - - - // 1번 모임에 더미 모임 멤버 추가 - List answerRequests = List.of( - AnswerRequest.builder() - .questionId(1L) - .answer("답변1") - .build(), - AnswerRequest.builder() - .questionId(2L) - .answer("답변2") - .build(), - AnswerRequest.builder() - .questionId(3L) - .answer("답변3") - .build() - ); - ApplyRecruitRequest applyRecruitRequest = ApplyRecruitRequest.builder() - .answers(answerRequests) - .build(); - for (int i = 0; i < 20; i++) { - Account account = accountService.getAccountByEmail("dummy" + i); - recruitService.applyRecruit(account, 1L, applyRecruitRequest); - } - recruitService.applyRecruit(admin2, 1L, applyRecruitRequest); - - recruitRepository.flush(); - - Plubbing plubbing1 = plubbingService.getPlubbing(1L); - List appliedAccountIds = appliedAccountRepository.findAllByRecruitId(plubbing1.getRecruit().getId()) - .stream().map(it -> it.getAccount().getId()).toList(); - - // 전체 승인 - appliedAccountIds.forEach(it -> recruitService.acceptApplicant(admin1, 1L, it)); +// +// for (int i = 0; i < 15; i++) { +// CreatePlubbingRequest form = CreatePlubbingRequest.builder() +// .subCategoryIds(List.of(52L)) +// .title("프로그래밍 모임" + i) +// .name("코딩 모임" + i) +// .goal("코틀린 마스터" + i) +// .introduce("모각코해요" + i) +// .mainImage(PLUB_MAIN_LOGO) +// .days(List.of("SAT", "SUN")) +// .onOff("ON") +// .address("서울특별시 강남구 테헤란로 427") +// .time("2200") +// .maxAccountNum(5) +// .questions(List.of("질문1", "질문2", "질문3")) +// .build(); +// plubbingService.createPlubbing(admin1, form); +// } +// +// for (int i = 0; i < 5; i++) { +// CreatePlubbingRequest form = CreatePlubbingRequest.builder() +// .subCategoryIds(List.of(16L)) +// .title("배드민턴 모임" + i) +// .name("배민모임" + i) +// .goal("배드민턴 스매쉬 잘 치기" + i) +// .introduce("우리는 배민 이다") +// .mainImage(PLUB_MAIN_LOGO) +// .days(List.of("THR", "FRI", "SAT", "SUN")) +// .onOff("OFF") +// .roadAddress("서울특별시 강남구 테헤란로 427") +// .address("서울특별시 강남구 테헤란로 333") +// .placeName("강남공원") +// .placePositionX(37.4981) +// .placePositionY(127.02761) +// .time("1700") +// .maxAccountNum(5) +// .questions(List.of("질문1", "질문2", "질문3")) +// .build(); +// plubbingService.createPlubbing(admin1, form); +// } +// +// +// // 1번 모임에 더미 모임 멤버 추가 +// List answerRequests = List.of( +// AnswerRequest.builder() +// .questionId(1L) +// .answer("답변1") +// .build(), +// AnswerRequest.builder() +// .questionId(2L) +// .answer("답변2") +// .build(), +// AnswerRequest.builder() +// .questionId(3L) +// .answer("답변3") +// .build() +// ); +// ApplyRecruitRequest applyRecruitRequest = ApplyRecruitRequest.builder() +// .answers(answerRequests) +// .build(); +// for (int i = 0; i < 20; i++) { +// Account account = accountService.getAccountByEmail("dummy" + i); +// recruitService.applyRecruit(account, 1L, applyRecruitRequest); +// } +// recruitService.applyRecruit(admin2, 1L, applyRecruitRequest); +// +// recruitRepository.flush(); +// +// Plubbing plubbing1 = plubbingService.getPlubbing(1L); +// List appliedAccountIds = appliedAccountRepository.findAllByRecruitId(plubbing1.getRecruit().getId()) +// .stream().map(it -> it.getAccount().getId()).toList(); +// +// // 전체 승인 +// appliedAccountIds.forEach(it -> recruitService.acceptApplicant(admin1, 1L, it)); log.info("[2] 모임,모집 더미 생성 완료."); } diff --git a/src/main/java/plub/plubserver/domain/account/dto/AccountDto.java b/src/main/java/plub/plubserver/domain/account/dto/AccountDto.java index 44da4684..3cfa3188 100644 --- a/src/main/java/plub/plubserver/domain/account/dto/AccountDto.java +++ b/src/main/java/plub/plubserver/domain/account/dto/AccountDto.java @@ -179,7 +179,7 @@ public static AccountIdResponse of(Account account) { } public record SmsRequest( - String to + String to ) { } @@ -198,6 +198,7 @@ public record SmsResponse( @Builder public SmsResponse { } + public static SmsResponse of(SmsResponseDTO result, LocalDateTime expirationTime) { return SmsResponse.builder() .result(result) @@ -206,17 +207,18 @@ public static SmsResponse of(SmsResponseDTO result, LocalDateTime expirationTime } } - public record SmsRequestDTO ( - String type, - String contentType, - String countryCode, - String from, - String content, - List messages + public record SmsRequestDTO( + String type, + String contentType, + String countryCode, + String from, + String content, + List messages ) { @Builder public SmsRequestDTO { } + public static SmsRequestDTO of(String from, String content, List messages) { return SmsRequestDTO.builder() .type("SMS") @@ -235,8 +237,9 @@ public record CertifySmsRequest( ) { } - public record SmsMessage(Object result) {} - + public record SmsMessage(Object result) { + } + public record LogoutResponse( boolean isLogout ) { diff --git a/src/main/java/plub/plubserver/domain/calendar/config/TaskSchedulerConfig.java b/src/main/java/plub/plubserver/domain/calendar/config/TaskSchedulerConfig.java new file mode 100644 index 00000000..1ae4848c --- /dev/null +++ b/src/main/java/plub/plubserver/domain/calendar/config/TaskSchedulerConfig.java @@ -0,0 +1,16 @@ +package plub.plubserver.domain.calendar.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +@Configuration +public class TaskSchedulerConfig { + + @Bean + public ThreadPoolTaskScheduler taskScheduler() { + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(Runtime.getRuntime().availableProcessors() * 2); + return scheduler; + } +} diff --git a/src/main/java/plub/plubserver/domain/calendar/service/CalendarService.java b/src/main/java/plub/plubserver/domain/calendar/service/CalendarService.java index 719fd582..b7ac7e74 100644 --- a/src/main/java/plub/plubserver/domain/calendar/service/CalendarService.java +++ b/src/main/java/plub/plubserver/domain/calendar/service/CalendarService.java @@ -3,7 +3,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import plub.plubserver.common.dto.PageResponse; @@ -36,10 +35,9 @@ public class CalendarService { private final CalendarAttendRepository calendarAttendRepository; private final PlubbingService plubbingService; private final NotificationService notificationService; - private final SchedulerService schedulerService; - public Calendar getCalendar(Long CalendarId) { - return calendarRepository.findById(CalendarId).orElseThrow( + public Calendar getCalendar(Long calendarId) { + return calendarRepository.findById(calendarId).orElseThrow( () -> new CalendarException(StatusCode.NOT_FOUNT_CALENDAR)); } @@ -132,11 +130,6 @@ public CalendarIdResponse createCalendar(Account loginAccount, Long plubbingId, ); }); - // 푸시 알림 스케줄러에 등록 - ThreadPoolTaskScheduler scheduler = schedulerService.getScheduler(); - if (calendar.getAlarmType() != CalendarAlarmType.NONE) { - schedulerService.addScheduler(calendar, scheduler); - } return CalendarIdResponse.of(calendar.getId()); } @@ -156,12 +149,6 @@ public CalendarIdResponse updateCalendar(Account loginAccount, Long plubbingId, ); }); - // 푸시 알림 스케줄러에 변경 - ThreadPoolTaskScheduler scheduler = schedulerService.getScheduler(); - if (calendar.getAlarmType() != CalendarAlarmType.NONE) { - schedulerService.changeScheduler(calendar, scheduler); - } - return CalendarIdResponse.of(calendar.getId()); } diff --git a/src/main/java/plub/plubserver/domain/calendar/service/SchedulerService.java b/src/main/java/plub/plubserver/domain/calendar/service/SchedulerService.java index fc4ff888..ef08dc52 100644 --- a/src/main/java/plub/plubserver/domain/calendar/service/SchedulerService.java +++ b/src/main/java/plub/plubserver/domain/calendar/service/SchedulerService.java @@ -1,83 +1,73 @@ package plub.plubserver.domain.calendar.service; -import org.springframework.scheduling.Trigger; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.support.CronTrigger; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import plub.plubserver.domain.calendar.model.Calendar; +import plub.plubserver.domain.calendar.repository.CalendarRepository; import plub.plubserver.domain.notification.dto.NotificationDto; import plub.plubserver.domain.notification.model.NotificationType; import plub.plubserver.domain.notification.service.NotificationService; import plub.plubserver.domain.plubbing.model.Plubbing; -import plub.plubserver.util.CronExpressionGenerator; +import java.time.Instant; import java.time.LocalDateTime; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.List; @Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Slf4j public class SchedulerService { - - private final ThreadPoolTaskScheduler scheduler; + private final CalendarRepository calendarRepository; private final NotificationService notificationService; + private final TaskScheduler taskScheduler; + + // DB에 저장된 모든 캘린더 정보를 가져와서 스케줄링 + @Scheduled(fixedRate = 60000) // 매분마다 실행 (적절한 주기로 변경 가능) + @Transactional + public void scheduleCalendars() { + try{ + List calendars = calendarRepository.findAll(); + LocalDateTime now = LocalDateTime.now(); + + for (Calendar calendar : calendars) { + LocalDateTime schedulerTime = parseSchedulerTime(calendar); + if (schedulerTime.isBefore(now)) { + // 스케줄 시간이 이미 지났으면 알림 전송 후 캘린더 삭제 + sendNotificationAndRemoveCalendar(calendar); + } else { + // 스케줄링 + taskScheduler.schedule(() -> sendNotificationAndRemoveCalendar(calendar), Instant.from(schedulerTime)); + } + } + } catch (Exception e) { + log.error("스케줄링 작업 중 예외 발생: " + e.getMessage(), e); + } - public SchedulerService(NotificationService notificationService) { - this.notificationService = notificationService; - this.scheduler = new ThreadPoolTaskScheduler(); - this.scheduler.initialize(); - } - - private final Map schedulerMap = new ConcurrentHashMap<>(); - - public ThreadPoolTaskScheduler getScheduler() { - return scheduler; - } - - public void addScheduler(Calendar calendar, ThreadPoolTaskScheduler scheduler) { - schedulerMap.put(calendar, scheduler); - LocalDateTime schedulerTime = parseSchedulerTime(calendar); - scheduler.schedule(getRunnable(calendar), getTrigger(schedulerTime)); - } - - public void changeScheduler(Calendar calendar, ThreadPoolTaskScheduler scheduler) { - schedulerMap.remove(calendar); - addScheduler(calendar, scheduler); - } - - public LocalDateTime parseSchedulerTime(Calendar calendar) { - LocalDateTime schedulerTime = LocalDateTime.parse(calendar.getStartedAt()+ "T" + calendar.getStartTime()); - LocalDateTime alarmTime = calendar.getAlarmType().getAlarmTime(schedulerTime); - return alarmTime; } - public void removeScheduler(Calendar calendar) { - schedulerMap.remove(calendar); - } - - private Runnable getRunnable(Calendar calendar) { - + private void sendNotificationAndRemoveCalendar(Calendar calendar) { Plubbing plubbing = calendar.getPlubbing(); - return () -> { - // 알람 로직 - plubbing.getMembers().forEach(member -> { - NotificationDto.NotifyParams params = NotificationDto.NotifyParams.builder() - .receiver(member) - .type(NotificationType.CREATE_UPDATE_CALENDAR) - .redirectTargetId(calendar.getId()) - .title(plubbing.getName()) - .content("곧 일정이 시작됩니다!\n : " + calendar.getTitle()) - .build(); - notificationService.pushMessage(params); - }); - - // 삭제 로직 - removeScheduler(calendar); - }; + plubbing.getMembers().forEach(member -> { + NotificationDto.NotifyParams params = NotificationDto.NotifyParams.builder() + .receiver(member) + .type(NotificationType.CREATE_UPDATE_CALENDAR) + .redirectTargetId(calendar.getId()) + .title(plubbing.getName()) + .content("곧 일정이 시작됩니다!\n : " + calendar.getTitle()) + .build(); + notificationService.pushMessage(params); + }); + calendarRepository.delete(calendar); } - private Trigger getTrigger(LocalDateTime schedulerTime) { - String cronExpression = CronExpressionGenerator.generate(schedulerTime); - return new CronTrigger(cronExpression); + private LocalDateTime parseSchedulerTime(Calendar calendar) { + LocalDateTime schedulerTime = LocalDateTime.parse(calendar.getStartedAt() + "T" + calendar.getStartTime()); + return calendar.getAlarmType().getAlarmTime(schedulerTime); } } diff --git a/src/test/java/plub/plubserver/domain/announcement/AnnouncementServiceTest.java b/src/test/java/plub/plubserver/domain/announcement/AnnouncementServiceTest.java index 60276143..41b72222 100644 --- a/src/test/java/plub/plubserver/domain/announcement/AnnouncementServiceTest.java +++ b/src/test/java/plub/plubserver/domain/announcement/AnnouncementServiceTest.java @@ -9,6 +9,7 @@ import plub.plubserver.domain.account.AccountTemplate; import plub.plubserver.domain.account.exception.AccountException; import plub.plubserver.domain.account.model.Account; +import plub.plubserver.domain.announcement.dto.AnnouncementDto; import plub.plubserver.domain.announcement.model.Announcement; import plub.plubserver.domain.announcement.repository.AnnouncementRepository; import plub.plubserver.domain.announcement.service.AnnouncementService; @@ -37,10 +38,10 @@ void createAnnouncement_success() { given(announcementRepository.save(any())) .willReturn(request.toEntity()); // when - announcementService.createAnnouncement(account, request); + AnnouncementDto.AnnouncementIdResponse announcement = announcementService.createAnnouncement(account, request); // then - assertThat(request.title()).isEqualTo(request.title()); + assertThat(announcement.announcementId()).isEqualTo(request.title()); } @Test