Skip to content

Commit

Permalink
feat: 예약 메일 전송 로직 작성
Browse files Browse the repository at this point in the history
  • Loading branch information
nohy6630 committed May 10, 2024
1 parent 927b35e commit 9b417e6
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import org.hibernate.annotations.Comment;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;

@Entity
Expand Down Expand Up @@ -35,12 +37,13 @@ public class EmailAlarm {
private boolean isSent;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
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.EmailSchedulerService;
import com.yeongjin.alarmserver.domain.repository.EmailAlarmRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,18 +17,9 @@
@Slf4j
public class EmailAlarmService {
private final EmailAlarmRepository emailAlarmRepository;
private final EmailSchedulerService emailSchedulerService;
private final JavaMailSender javaMailSender;

private void saveEmailAlarmToStream(EmailAlarm emailAlarm) {

// List<ObjectRecord<String, EmailAlarm>> records = redisTemplate.opsForStream()
// .read(EmailAlarm.class, StreamOffset.fromStart("emailAlarmStream"));
// records.stream()
// .map(ObjectRecord::getValue)
// .forEach(System.out::println);

}

@Transactional
public Long sendImmediateEmail(ImmediateEmailReq immediateEmailReq) {
EmailAlarm emailAlarm = emailAlarmRepository.save(
Expand All @@ -40,22 +29,7 @@ public Long sendImmediateEmail(ImmediateEmailReq immediateEmailReq) {
immediateEmailReq.getContent()
)
);

saveEmailAlarmToStream(emailAlarm);

// MimeMessage mimeMessage = javaMailSender.createMimeMessage();
// try {
// MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");
// mimeMessageHelper.setTo(immediateEmailReq.getRecipients().toArray(new String[0]));
// mimeMessageHelper.setSubject(immediateEmailReq.getSubject());
// mimeMessageHelper.setText(immediateEmailReq.getContent(), false);
// javaMailSender.send(mimeMessage);
// log.info("Success");
// } catch (MessagingException e) {
// log.info("Fail");
// throw new RuntimeException(e);
// }

emailSchedulerService.registerEmailAlarmToStream(emailAlarm);
return emailAlarm.getId();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;

@Service
Expand All @@ -18,14 +20,21 @@ public class EmailSchedulerService {
private final RedisTemplate<String, Object> redisTemplate;
private final EmailAlarmRepository emailAlarmRepository;

//todo 동시성 처리
public void registerEmailAlarmToStream(EmailAlarm emailAlarm) {
redisTemplate.opsForStream()
.add(StreamRecords.newRecord()
.in("emailAlarmStream")
.ofObject(emailAlarm));
emailAlarm.setSent();
}

@Scheduled(cron = "30 * * * * *", zone = "Asia/Seoul")
public void registerEmailAlarmToStream() {
List<EmailAlarm> emailAlarms = emailAlarmRepository.findBySendTime(LocalDateTime.now().withSecond(0));
public void scanEmailAlarmInDatabase() {
LocalDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime();
List<EmailAlarm> emailAlarms = emailAlarmRepository.findEmailsToSend(now.withSecond(0));
for (EmailAlarm emailAlarm : emailAlarms) {
redisTemplate.opsForStream()
.add(StreamRecords.newRecord()
.in("emailAlarmStream")
.ofObject(emailAlarm));
registerEmailAlarmToStream(emailAlarm);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.yeongjin.alarmserver.domain.emailSender.service;

import com.yeongjin.alarmserver.domain.api.entity.EmailAlarm;
import jakarta.annotation.PostConstruct;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.StreamOffset;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.connection.stream.StringRecord;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class EmailSenderService {
private final JavaMailSender javaMailSender;
private final RedisTemplate<String, Object> redisTemplate;

@PostConstruct
public void createStreamGroup() {
try {
redisTemplate.opsForStream().createGroup("emailAlarmStream", "myGroup");
} catch (Exception e) {
log.info("Group already exists");
}
}

private void sendEmail(EmailAlarm emailAlarm) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
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);
javaMailSender.send(mimeMessage);
log.info("Send Success");
} catch (MessagingException e) {
log.info("Send Fail");
throw new RuntimeException(e);
}
}

@Scheduled(cron = "0 * * * * *", zone = "Asia/Seoul")
public void fetchDataFromStream() {
List<ObjectRecord<String, EmailAlarm>> records = redisTemplate.opsForStream()
.read(EmailAlarm.class, StreamOffset.fromStart("emailAlarmStream"));
records.stream()
.map(ObjectRecord::getValue)
.forEach(this::sendEmail);
records.stream()
.map(ObjectRecord::getId)
.forEach(recordId -> redisTemplate.opsForStream()
.acknowledge("emailAlarmStream", "myGroup", recordId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ public interface EmailAlarmRepository extends JpaRepository<EmailAlarm, Long> {
@Query("select e.id from EmailAlarm e where e.isSent = true")
List<Long> findIdsIsSent();

List<EmailAlarm> findBySendTime(LocalDateTime sendTime);
@Query("select e from EmailAlarm e where e.sendTime = :sendTime and e.isSent = false")
List<EmailAlarm> findEmailsToSend(LocalDateTime sendTime);
}

0 comments on commit 9b417e6

Please sign in to comment.