diff --git a/src/main/java/com/yeongjin/alarmserver/domain/api/controller/EmailAlarmController.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/controller/SendAlarmController.java similarity index 57% rename from src/main/java/com/yeongjin/alarmserver/domain/api/controller/EmailAlarmController.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/controller/SendAlarmController.java index 1ff172e..c9fd8e9 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/api/controller/EmailAlarmController.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/controller/SendAlarmController.java @@ -1,8 +1,8 @@ -package com.yeongjin.alarmserver.domain.api.controller; +package com.yeongjin.alarmserver.domain.alarm.controller; -import com.yeongjin.alarmserver.domain.api.dto.request.ImmediateEmailReq; -import com.yeongjin.alarmserver.domain.api.dto.request.ScheduledEmailReq; -import com.yeongjin.alarmserver.domain.api.service.EmailAlarmService; +import com.yeongjin.alarmserver.domain.alarm.dto.request.SendImmediateAlarmReq; +import com.yeongjin.alarmserver.domain.alarm.dto.request.SendScheduledAlarmReq; +import com.yeongjin.alarmserver.domain.alarm.service.SendAlarmService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -16,20 +16,20 @@ @RestController @RequiredArgsConstructor @RequestMapping("/emails") -public class EmailAlarmController { - private final EmailAlarmService emailAlarmService; +public class SendAlarmController { + private final SendAlarmService sendAlarmService; @PostMapping("/immediate") - public ResponseEntity sendImmediateEmail(@RequestBody @Valid ImmediateEmailReq immediateEmailReq) { - Long alarmId = emailAlarmService.sendImmediateEmail(immediateEmailReq); + public ResponseEntity sendImmediateEmail(@RequestBody @Valid SendImmediateAlarmReq sendImmediateAlarmReq) { + Long alarmId = sendAlarmService.sendImmediateEmail(sendImmediateAlarmReq); return ResponseEntity .created(URI.create("/emails/" + alarmId)) .build(); } @PostMapping("/scheduled") - public ResponseEntity sendScheduledEmail(@RequestBody @Valid ScheduledEmailReq scheduledEmailReq) { - Long alarmId = emailAlarmService.sendScheduledEmail(scheduledEmailReq); + public ResponseEntity sendScheduledEmail(@RequestBody @Valid SendScheduledAlarmReq sendScheduledAlarmReq) { + Long alarmId = sendAlarmService.sendScheduledEmail(sendScheduledAlarmReq); return ResponseEntity .created(URI.create("/emails/" + alarmId)) .build(); diff --git a/src/main/java/com/yeongjin/alarmserver/domain/api/dto/request/ImmediateEmailReq.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/dto/request/SendImmediateAlarmReq.java similarity index 84% rename from src/main/java/com/yeongjin/alarmserver/domain/api/dto/request/ImmediateEmailReq.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/dto/request/SendImmediateAlarmReq.java index 8d4738a..debd7bd 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/api/dto/request/ImmediateEmailReq.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/dto/request/SendImmediateAlarmReq.java @@ -1,4 +1,4 @@ -package com.yeongjin.alarmserver.domain.api.dto.request; +package com.yeongjin.alarmserver.domain.alarm.dto.request; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.Size; @@ -10,7 +10,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter -public class ImmediateEmailReq { +public class SendImmediateAlarmReq { @Size(min = 1, message = "at least one recipient must be selected") private List recipients; diff --git a/src/main/java/com/yeongjin/alarmserver/domain/api/dto/request/ScheduledEmailReq.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/dto/request/SendScheduledAlarmReq.java similarity index 89% rename from src/main/java/com/yeongjin/alarmserver/domain/api/dto/request/ScheduledEmailReq.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/dto/request/SendScheduledAlarmReq.java index 4ae9f04..23760e4 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/api/dto/request/ScheduledEmailReq.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/dto/request/SendScheduledAlarmReq.java @@ -1,4 +1,4 @@ -package com.yeongjin.alarmserver.domain.api.dto.request; +package com.yeongjin.alarmserver.domain.alarm.dto.request; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.validation.constraints.NotEmpty; @@ -13,7 +13,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter -public class ScheduledEmailReq { +public class SendScheduledAlarmReq { @Size(min = 1, message = "at least one recipient must be selected") private List recipients; diff --git a/src/main/java/com/yeongjin/alarmserver/domain/api/entity/EmailAlarm.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/entity/Alarm.java similarity index 78% rename from src/main/java/com/yeongjin/alarmserver/domain/api/entity/EmailAlarm.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/entity/Alarm.java index 738725b..1ccc2b2 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/api/entity/EmailAlarm.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/entity/Alarm.java @@ -1,4 +1,4 @@ -package com.yeongjin.alarmserver.domain.api.entity; +package com.yeongjin.alarmserver.domain.alarm.entity; import jakarta.persistence.*; @@ -16,7 +16,7 @@ @AllArgsConstructor(access = AccessLevel.PRIVATE) @Builder @Comment("메일") -public class EmailAlarm { +public class Alarm { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -36,9 +36,9 @@ public class EmailAlarm { @Comment("발송 여부") private boolean isSent; - public static EmailAlarm ofImmediate(List recipients, String subject, String content) { + public static Alarm ofImmediate(List recipients, String subject, String content) { LocalDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime(); - return EmailAlarm.builder() + return Alarm.builder() .recipients(recipients) .subject(subject) .content(content) @@ -47,8 +47,8 @@ public static EmailAlarm ofImmediate(List recipients, String subject, St .build(); } - public static EmailAlarm ofScheduled(List recipients, String subject, String content, LocalDateTime sendTime) { - return EmailAlarm.builder() + public static Alarm ofScheduled(List recipients, String subject, String content, LocalDateTime sendTime) { + return Alarm.builder() .recipients(recipients) .subject(subject) .content(content) diff --git a/src/main/java/com/yeongjin/alarmserver/domain/alarm/repository/AlarmRepository.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/repository/AlarmRepository.java new file mode 100644 index 0000000..c15a803 --- /dev/null +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/repository/AlarmRepository.java @@ -0,0 +1,16 @@ +package com.yeongjin.alarmserver.domain.alarm.repository; + +import com.yeongjin.alarmserver.domain.alarm.entity.Alarm; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.time.LocalDateTime; +import java.util.List; + +public interface AlarmRepository extends JpaRepository { + @Query("select e.id from Alarm e where e.isSent = true") + List findIdsIsSent(); + + @Query("select e from Alarm e where e.sendTime <= :sendTime and e.isSent = false") + List findEmailsToSend(LocalDateTime sendTime); +} diff --git a/src/main/java/com/yeongjin/alarmserver/domain/emailCleaner/service/CleanDBService.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/CleanDBService.java similarity index 59% rename from src/main/java/com/yeongjin/alarmserver/domain/emailCleaner/service/CleanDBService.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/service/CleanDBService.java index 10c5504..8488494 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/emailCleaner/service/CleanDBService.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/CleanDBService.java @@ -1,6 +1,6 @@ -package com.yeongjin.alarmserver.domain.emailCleaner.service; +package com.yeongjin.alarmserver.domain.alarm.service; -import com.yeongjin.alarmserver.domain.repository.EmailAlarmRepository; +import com.yeongjin.alarmserver.domain.alarm.repository.AlarmRepository; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -12,12 +12,12 @@ @RequiredArgsConstructor @Transactional(readOnly = true) public class CleanDBService { - private final EmailAlarmRepository emailAlarmRepository; + private final AlarmRepository alarmRepository; @Scheduled(cron = "0 0 3 * * *", zone = "Asia/Seoul") @Transactional public void deleteSentEmails() { - List ids = emailAlarmRepository.findIdsIsSent(); - emailAlarmRepository.deleteAllByIdInBatch(ids); + List ids = alarmRepository.findIdsIsSent(); + alarmRepository.deleteAllByIdInBatch(ids); } } diff --git a/src/main/java/com/yeongjin/alarmserver/domain/emailScheduler/service/SendEmailPublisher.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmPublisher.java similarity index 61% rename from src/main/java/com/yeongjin/alarmserver/domain/emailScheduler/service/SendEmailPublisher.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmPublisher.java index b824791..8256645 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/emailScheduler/service/SendEmailPublisher.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmPublisher.java @@ -1,13 +1,11 @@ -package com.yeongjin.alarmserver.domain.emailScheduler.service; +package com.yeongjin.alarmserver.domain.alarm.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.yeongjin.alarmserver.domain.api.entity.EmailAlarm; -import com.yeongjin.alarmserver.domain.emailSender.service.SendEmailSubscriber; -import com.yeongjin.alarmserver.domain.repository.EmailAlarmRepository; +import com.yeongjin.alarmserver.domain.alarm.entity.Alarm; +import com.yeongjin.alarmserver.domain.alarm.repository.AlarmRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.connection.stream.StreamRecords; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.scheduling.annotation.Scheduled; @@ -22,9 +20,9 @@ @Service @RequiredArgsConstructor @Slf4j -public class SendEmailPublisher { +public class SendAlarmPublisher { private final RedisTemplate redisTemplate; - private final EmailAlarmRepository emailAlarmRepository; + private final AlarmRepository alarmRepository; private final ObjectMapper objectMapper; private final ChannelTopic channelTopic; @@ -33,16 +31,16 @@ public class SendEmailPublisher { public void scanDatabase() { LocalDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime().withSecond(0); log.info("Scan Database at " + now); - List emailAlarms = emailAlarmRepository.findEmailsToSend(now); - for (EmailAlarm emailAlarm : emailAlarms) { - emailAlarm.setSent(); - publishToRedis(emailAlarm); + List alarms = alarmRepository.findEmailsToSend(now); + for (Alarm alarm : alarms) { + alarm.setSent(); + publishToRedis(alarm); } } - public void publishToRedis(EmailAlarm emailAlarm) { + public void publishToRedis(Alarm alarm) { try { - String message = objectMapper.writeValueAsString(emailAlarm); + String message = objectMapper.writeValueAsString(alarm); redisTemplate.convertAndSend(channelTopic.getTopic(), message); } catch (JsonProcessingException e) { log.warn("Publish Message Failed"); diff --git a/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmService.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmService.java new file mode 100644 index 0000000..1dce504 --- /dev/null +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmService.java @@ -0,0 +1,49 @@ +package com.yeongjin.alarmserver.domain.alarm.service; + +import com.yeongjin.alarmserver.domain.alarm.dto.request.SendImmediateAlarmReq; +import com.yeongjin.alarmserver.domain.alarm.dto.request.SendScheduledAlarmReq; +import com.yeongjin.alarmserver.domain.alarm.entity.Alarm; +import com.yeongjin.alarmserver.domain.alarm.repository.AlarmRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Slf4j +public class SendAlarmService { + private final AlarmRepository alarmRepository; + private final SendAlarmPublisher sendEmailPublisher; + private final SendAlarmSubscriber sendAlarmSubscriber; + private final JavaMailSender javaMailSender; + + @Transactional + public Long sendImmediateEmail(SendImmediateAlarmReq sendImmediateAlarmReq) { + Alarm alarm = alarmRepository.save( + Alarm.ofImmediate( + sendImmediateAlarmReq.getRecipients(), + sendImmediateAlarmReq.getSubject(), + sendImmediateAlarmReq.getContent() + ) + ); + alarm.setSent(); + sendEmailPublisher.publishToRedis(alarm); + return alarm.getId(); + } + + @Transactional + public Long sendScheduledEmail(SendScheduledAlarmReq sendScheduledAlarmReq) { + Alarm alarm = alarmRepository.save( + Alarm.ofScheduled( + sendScheduledAlarmReq.getRecipients(), + sendScheduledAlarmReq.getSubject(), + sendScheduledAlarmReq.getContent(), + sendScheduledAlarmReq.getSendTime().withSecond(0) + ) + ); + return alarm.getId(); + } +} diff --git a/src/main/java/com/yeongjin/alarmserver/domain/emailSender/service/SendEmailSubscriber.java b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmSubscriber.java similarity index 63% rename from src/main/java/com/yeongjin/alarmserver/domain/emailSender/service/SendEmailSubscriber.java rename to src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmSubscriber.java index 6a85043..e546ba6 100644 --- a/src/main/java/com/yeongjin/alarmserver/domain/emailSender/service/SendEmailSubscriber.java +++ b/src/main/java/com/yeongjin/alarmserver/domain/alarm/service/SendAlarmSubscriber.java @@ -1,8 +1,8 @@ -package com.yeongjin.alarmserver.domain.emailSender.service; +package com.yeongjin.alarmserver.domain.alarm.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.yeongjin.alarmserver.domain.api.entity.EmailAlarm; +import com.yeongjin.alarmserver.domain.alarm.entity.Alarm; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; @@ -14,26 +14,26 @@ @Service @RequiredArgsConstructor @Slf4j -public class SendEmailSubscriber { +public class SendAlarmSubscriber { private final JavaMailSender javaMailSender; private final ObjectMapper objectMapper; public void sendEmail(String message, String channel) throws JsonProcessingException { log.info("Received message: " + message + " from channel: " + channel); - EmailAlarm emailAlarm = objectMapper.readValue(message, EmailAlarm.class); + Alarm alarm = objectMapper.readValue(message, Alarm.class); try { - javaMailSender.send(createMimeMessage(emailAlarm)); + javaMailSender.send(createMimeMessage(alarm)); } catch (MessagingException e) { log.warn("Create Mime Message Failed"); } } - private MimeMessage createMimeMessage(EmailAlarm emailAlarm) throws MessagingException { + private MimeMessage createMimeMessage(Alarm alarm) throws MessagingException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); - mimeMessageHelper.setTo(emailAlarm.getRecipients().toArray(new String[0])); - mimeMessageHelper.setSubject(emailAlarm.getSubject()); - mimeMessageHelper.setText(emailAlarm.getContent(), false); + mimeMessageHelper.setTo(alarm.getRecipients().toArray(new String[0])); + mimeMessageHelper.setSubject(alarm.getSubject()); + mimeMessageHelper.setText(alarm.getContent(), false); return mimeMessage; } } diff --git a/src/main/java/com/yeongjin/alarmserver/domain/api/service/EmailAlarmService.java b/src/main/java/com/yeongjin/alarmserver/domain/api/service/EmailAlarmService.java deleted file mode 100644 index 65fb3ad..0000000 --- a/src/main/java/com/yeongjin/alarmserver/domain/api/service/EmailAlarmService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.yeongjin.alarmserver.domain.api.service; - -import com.yeongjin.alarmserver.domain.api.dto.request.ImmediateEmailReq; -import com.yeongjin.alarmserver.domain.api.dto.request.ScheduledEmailReq; -import com.yeongjin.alarmserver.domain.api.entity.EmailAlarm; -import com.yeongjin.alarmserver.domain.emailScheduler.service.SendEmailPublisher; -import com.yeongjin.alarmserver.domain.emailSender.service.SendEmailSubscriber; -import com.yeongjin.alarmserver.domain.repository.EmailAlarmRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Slf4j -public class EmailAlarmService { - private final EmailAlarmRepository emailAlarmRepository; - private final SendEmailPublisher sendEmailPublisher; - private final SendEmailSubscriber sendEmailSubscriber; - private final JavaMailSender javaMailSender; - - @Transactional - public Long sendImmediateEmail(ImmediateEmailReq immediateEmailReq) { - EmailAlarm emailAlarm = emailAlarmRepository.save( - EmailAlarm.ofImmediate( - immediateEmailReq.getRecipients(), - immediateEmailReq.getSubject(), - immediateEmailReq.getContent() - ) - ); - emailAlarm.setSent(); - sendEmailPublisher.publishToRedis(emailAlarm); - return emailAlarm.getId(); - } - - @Transactional - public Long sendScheduledEmail(ScheduledEmailReq scheduledEmailReq) { - EmailAlarm emailAlarm = emailAlarmRepository.save( - EmailAlarm.ofScheduled( - scheduledEmailReq.getRecipients(), - scheduledEmailReq.getSubject(), - scheduledEmailReq.getContent(), - scheduledEmailReq.getSendTime().withSecond(0) - ) - ); - return emailAlarm.getId(); - } -} diff --git a/src/main/java/com/yeongjin/alarmserver/domain/repository/EmailAlarmRepository.java b/src/main/java/com/yeongjin/alarmserver/domain/repository/EmailAlarmRepository.java deleted file mode 100644 index 19021ce..0000000 --- a/src/main/java/com/yeongjin/alarmserver/domain/repository/EmailAlarmRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.yeongjin.alarmserver.domain.repository; - -import com.yeongjin.alarmserver.domain.api.entity.EmailAlarm; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; - -import java.time.LocalDateTime; -import java.util.List; - -public interface EmailAlarmRepository extends JpaRepository { - @Query("select e.id from EmailAlarm e where e.isSent = true") - List findIdsIsSent(); - - @Query("select e from EmailAlarm e where e.sendTime <= :sendTime and e.isSent = false") - List findEmailsToSend(LocalDateTime sendTime); -} diff --git a/src/main/java/com/yeongjin/alarmserver/global/config/RedisConfig.java b/src/main/java/com/yeongjin/alarmserver/global/config/RedisConfig.java index c453cb6..cf55c39 100644 --- a/src/main/java/com/yeongjin/alarmserver/global/config/RedisConfig.java +++ b/src/main/java/com/yeongjin/alarmserver/global/config/RedisConfig.java @@ -1,6 +1,6 @@ package com.yeongjin.alarmserver.global.config; -import com.yeongjin.alarmserver.domain.emailSender.service.SendEmailSubscriber; +import com.yeongjin.alarmserver.domain.alarm.service.SendAlarmSubscriber; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,8 +35,8 @@ public RedisTemplate redisTemplate(RedisConnectionFactory redisC } @Bean - public MessageListenerAdapter messageListenerAdapter(SendEmailSubscriber sendEmailSubscriber) { - return new MessageListenerAdapter(sendEmailSubscriber, "sendEmail"); + public MessageListenerAdapter messageListenerAdapter(SendAlarmSubscriber sendAlarmSubscriber) { + return new MessageListenerAdapter(sendAlarmSubscriber, "sendEmail"); } @Bean