Skip to content

Commit

Permalink
feat: 이메일 전송 실패시 예외처리 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
nohy6630 committed Jun 22, 2024
1 parent 0af40c3 commit 9cbe078
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ public class Alarm {
@Comment("메일 발송 시간")
private LocalDateTime sendTime;

@Comment("발송 여부")
private boolean isSent;
@Comment("알림 상태")
@Enumerated(EnumType.STRING)
private AlarmStatus status;

public static Alarm ofImmediate(List<String> recipients, String subject, String content) {
LocalDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime();
return Alarm.builder()
.recipients(recipients)
.subject(subject)
.content(content)
.sendTime(now.withSecond(0))
.isSent(false)
.sendTime(now.withSecond(0).withNano(0))
.status(AlarmStatus.SENT)
.build();
}

Expand All @@ -52,12 +53,12 @@ public static Alarm ofScheduled(List<String> recipients, String subject, String
.recipients(recipients)
.subject(subject)
.content(content)
.sendTime(sendTime.withSecond(0))
.isSent(false)
.sendTime(sendTime.withSecond(0).withNano(0))
.status(AlarmStatus.RESERVED)
.build();
}

public void setSent() {
this.isSent = true;
public void setStatus(AlarmStatus status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.yeongjin.alarmserver.domain.alarm.entity;

public enum AlarmStatus {
RESERVED, PUBLISHED, SENT
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import java.util.List;

public interface AlarmRepository extends JpaRepository<Alarm, Long> {
@Query("select e.id from Alarm e where e.isSent = true")
@Query("select e.id from Alarm e where e.status = 'SENT'")
List<Long> findIdsIsSent();

@Query("select e from Alarm e where e.sendTime <= :sendTime and e.isSent = false")
@Query("select e from Alarm e where e.sendTime <= :sendTime and e.status = 'RESERVED'")
List<Alarm> findEmailsToSend(LocalDateTime sendTime);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yeongjin.alarmserver.domain.alarm.entity.Alarm;
import com.yeongjin.alarmserver.domain.alarm.entity.AlarmStatus;
import com.yeongjin.alarmserver.domain.alarm.repository.AlarmRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -20,6 +21,7 @@
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(readOnly = true)
public class SendAlarmPublisher {
private final RedisTemplate<String, Object> redisTemplate;
private final AlarmRepository alarmRepository;
Expand All @@ -29,21 +31,22 @@ public class SendAlarmPublisher {
@Scheduled(cron = "30 * * * * *", zone = "Asia/Seoul")
@Transactional
public void scanDatabase() {
LocalDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime().withSecond(0);
LocalDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime().withSecond(0).withNano(0);
log.info("Scan Database at " + now);
List<Alarm> alarms = alarmRepository.findEmailsToSend(now);
for (Alarm alarm : alarms) {
alarm.setSent();
for (Alarm alarm : alarms)
publishToRedis(alarm);
}
}

@Transactional
public void publishToRedis(Alarm alarm) {
try {
String message = objectMapper.writeValueAsString(alarm);
String message = objectMapper.writeValueAsString(alarm.getId());
redisTemplate.convertAndSend(channelTopic.getTopic(), message);
alarm.setStatus(AlarmStatus.PUBLISHED);
} catch (JsonProcessingException e) {
log.warn("Publish Message Failed");
alarm.setStatus(AlarmStatus.RESERVED);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@

@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(
Expand All @@ -29,7 +25,6 @@ public Long sendImmediateEmail(SendImmediateAlarmReq sendImmediateAlarmReq) {
sendImmediateAlarmReq.getContent()
)
);
alarm.setSent();
sendEmailPublisher.publishToRedis(alarm);
return alarm.getId();
}
Expand All @@ -41,7 +36,7 @@ public Long sendScheduledEmail(SendScheduledAlarmReq sendScheduledAlarmReq) {
sendScheduledAlarmReq.getRecipients(),
sendScheduledAlarmReq.getSubject(),
sendScheduledAlarmReq.getContent(),
sendScheduledAlarmReq.getSendTime().withSecond(0)
sendScheduledAlarmReq.getSendTime()
)
);
return alarm.getId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,37 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yeongjin.alarmserver.domain.alarm.entity.Alarm;
import com.yeongjin.alarmserver.domain.alarm.entity.AlarmStatus;
import com.yeongjin.alarmserver.domain.alarm.repository.AlarmRepository;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(readOnly = true)
public class SendAlarmSubscriber {
private final JavaMailSender javaMailSender;
private final ObjectMapper objectMapper;
private final AlarmRepository alarmRepository;

@Transactional
public void sendEmail(String message, String channel) throws JsonProcessingException {
log.info("Received message: " + message + " from channel: " + channel);
Alarm alarm = objectMapper.readValue(message, Alarm.class);
log.info("Receive Message from " + channel);
Long alarmId = objectMapper.readValue(message, Long.class);
Alarm alarm = alarmRepository.findById(alarmId).orElseThrow();
try {
javaMailSender.send(createMimeMessage(alarm));
} catch (MessagingException e) {
log.warn("Create Mime Message Failed");
alarm.setStatus(AlarmStatus.SENT);
} catch (Exception e) {
log.warn("Send Email Failed");
alarm.setStatus(AlarmStatus.RESERVED);
}
}

Expand Down

0 comments on commit 9cbe078

Please sign in to comment.