Skip to content

Commit

Permalink
폼 상태 변경 시 메일 전송 기능 문제 해결 (#321)
Browse files Browse the repository at this point in the history
  • Loading branch information
juno-junho authored Apr 24, 2024
1 parent a392d88 commit 98efa89
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.spaceclub.global.advice;

import com.spaceclub.global.exception.MailTemplateException;
import com.spaceclub.global.exception.ProfanityFoundException;
import com.spaceclub.global.exception.TokenException;
import com.spaceclub.global.response.ErrorResponse;
Expand Down Expand Up @@ -70,7 +71,7 @@ public ErrorResponse handleHttpRequestMethodNotSupportedException(Exception exce
@ExceptionHandler
public ErrorResponse handleInternalServerException(Exception exception) {
String exceptionName = exception.getClass().getSimpleName();
log.info("서버 에러, exception name: {}", exceptionName);
log.warn("서버 에러", exception);

return new ErrorResponse(exceptionName, exception.getMessage());
}
Expand All @@ -89,4 +90,10 @@ public ErrorResponse handleValidationExceptions(MethodArgumentNotValidException
return new ErrorResponse(ex.getClass().getSimpleName(), String.join(", ", errors));
}

@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(MailTemplateException.class)
public void handleMailTemplateException(MailTemplateException exception) {
throw new RuntimeException(exception.getMessage());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.spaceclub.global.exception;

public class MailTemplateException extends RuntimeException {

public MailTemplateException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MailTrackerRepository extends JpaRepository<MailHistory, Long> {
public interface MailHistoryRepository extends JpaRepository<MailHistory, Long> {

int countByIsSentFalse();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.spaceclub.notification.mail.config.MailProperties;
import com.spaceclub.notification.mail.domain.MailHistory;
import com.spaceclub.notification.mail.domain.TemplateName;
import com.spaceclub.notification.mail.domain.repository.MailTrackerRepository;
import com.spaceclub.notification.mail.domain.repository.MailHistoryRepository;
import com.spaceclub.notification.mail.domain.repository.TemplateRepository;
import com.spaceclub.notification.mail.service.event.MailEvent;
import com.spaceclub.notification.mail.service.vo.EventStatusChangeMailInfo;
Expand All @@ -30,12 +30,13 @@ public class EventMailService {
private final JavaMailSender emailSender;
private final SpringTemplateEngine templateEngine;
private final MailProperties mailProperties;
private final MailTrackerRepository mailTrackerRepository;
private final MailHistoryRepository mailHistoryRepository;
private final TemplateRepository templateRepository;

@Async
@TransactionalEventListener
public void sendEmail(MailEvent mailEvent) {
log.info("메일 이벤트 호출 | MailEvent : {}", mailEvent);
MailInfo mailInfo = mailEvent.mailInfo();

TemplateName templateName = TemplateName.findByTemplateName(mailInfo.templateName());
Expand All @@ -58,7 +59,7 @@ public void sendEmail(MailEvent mailEvent) {
case WELCOME -> WelcomeMailInfo.createMailHistory(mailInfo, isSent);
case EVENT_STATUS_CHANGED -> EventStatusChangeMailInfo.createMailHistory(mailInfo, isSent);
};
mailTrackerRepository.save(mailHistory);
mailHistoryRepository.save(mailHistory);
}
log.debug("메일 발송 완료!");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.spaceclub.notification.mail.service;

import com.spaceclub.notification.mail.domain.repository.MailTrackerRepository;
import com.spaceclub.notification.mail.domain.repository.MailHistoryRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
Expand All @@ -12,14 +12,14 @@
@RequiredArgsConstructor
public class MailRetryService {

private final MailTrackerRepository mailTrackerRepository;
private final MailHistoryRepository mailHistoryRepository;
private final RetryMailSender retryMailSender;

@Async
@Transactional
public void retryAllFailedEmails() {
// 실패한 email count query 생성
int sendFailedMailCount = mailTrackerRepository.countByIsSentFalse();
int sendFailedMailCount = mailHistoryRepository.countByIsSentFalse();
final int chunkSize = 10;

// partition size = count / chunk size 올림
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.spaceclub.notification.mail.service;

import com.spaceclub.global.exception.MailTemplateException;
import com.spaceclub.notification.mail.domain.Template;
import com.spaceclub.notification.mail.domain.repository.TemplateRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Profile("!test")
@RequiredArgsConstructor
public class MailTemplateLoader implements ApplicationRunner {

private final static int MAIL_TEMPLATE_COUNT = 2;

private final TemplateRepository templateRepository;

@Override
public void run(ApplicationArguments args) {
List<Template> mailTemplates = templateRepository.findAll();

if (mailTemplates.size() != MAIL_TEMPLATE_COUNT) {
throw new MailTemplateException("메일 템플릿이 2개가 아닙니다.");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.spaceclub.notification.mail.config.MailProperties;
import com.spaceclub.notification.mail.domain.MailHistory;
import com.spaceclub.notification.mail.domain.repository.MailTrackerRepository;
import com.spaceclub.notification.mail.domain.repository.MailHistoryRepository;
import com.spaceclub.notification.mail.domain.repository.TemplateRepository;
import com.spaceclub.notification.mail.service.vo.MailInfo;
import jakarta.mail.MessagingException;
Expand All @@ -29,13 +29,13 @@ public class RetryMailSender {
private final JavaMailSender emailSender;
private final SpringTemplateEngine templateEngine;
private final MailProperties mailProperties;
private final MailTrackerRepository mailTrackerRepository;
private final MailHistoryRepository mailHistoryRepository;
private final TemplateRepository templateRepository;

@Async
public void sendEmail(int partitionNumber, int chunkSize) {
Pageable pageRequest = PageRequest.of(partitionNumber, chunkSize);
Slice<MailHistory> mailTrackers = mailTrackerRepository.findAllByIsSentFalse(pageRequest);
Slice<MailHistory> mailTrackers = mailHistoryRepository.findAllByIsSentFalse(pageRequest);

mailTrackers.forEach(this::sendEachMail);
}
Expand All @@ -56,7 +56,7 @@ private void sendEachMail(MailHistory mailHistory) {
return;
}
mailHistory.changeToSent();
mailTrackerRepository.save(mailHistory);
mailHistoryRepository.save(mailHistory);
log.debug("메일 재전송 완료");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public enum ParticipationStatus {

public static String getStatusName(String eventStatus) {
return Arrays.stream(values())
.filter(status -> status.statusName.equals(eventStatus))
.filter(status -> status.name().equalsIgnoreCase(eventStatus))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이벤트 상태입니다."))
.statusName;
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/com/spaceclub/global/utils/EncryptionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ class EncryptionTest {
void jasypt를_통해_암호화에_성공한다() {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();

encryptor.setPassword("heenahan"); // 암호화 및 복호화 시 사용하는 패스워드
encryptor.setPassword(""); // 암호화 및 복호화 시 사용하는 패스워드
encryptor.setAlgorithm("PBEWithMD5AndDES");
encryptor.setStringOutputType("base64");

String url = "www.dotori.com";
String url = "";
String username = "";
String password = "";
String urlResult = encryptor.encrypt(url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.spaceclub.notification.mail.domain.MailHistory;
import com.spaceclub.notification.mail.domain.Template;
import com.spaceclub.notification.mail.domain.TemplateName;
import com.spaceclub.notification.mail.domain.repository.MailTrackerRepository;
import com.spaceclub.notification.mail.domain.repository.MailHistoryRepository;
import com.spaceclub.notification.mail.domain.repository.TemplateRepository;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.AfterEach;
Expand All @@ -26,7 +26,7 @@ class TemplateNameRepositoryTest {
@Autowired
private TemplateRepository templateRepository;
@Autowired
private MailTrackerRepository mailTrackerRepository;
private MailHistoryRepository mailHistoryRepository;
@Autowired
private EntityManager entityManager;

Expand Down Expand Up @@ -68,7 +68,7 @@ void setUp() {
.isSent(false)
.build();

mailTrackerRepository.saveAll(List.of(mailHistory1, mailHistory2, mailHistory3));
mailHistoryRepository.saveAll(List.of(mailHistory1, mailHistory2, mailHistory3));
}

@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.spaceclub.notification.mail.service;

import com.spaceclub.global.exception.MailTemplateException;
import com.spaceclub.notification.mail.domain.Template;
import com.spaceclub.notification.mail.domain.repository.TemplateRepository;
import org.junit.jupiter.api.Test;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

@SpringBootTest
class MailTemplateLoaderTest {

@MockBean
private TemplateRepository templateRepository;

@Test
void DB에_메일템플릿이_두개일경우_예외를_발생하지_않는다() {
// given
MailTemplateLoader mailTemplateLoader = new MailTemplateLoader(templateRepository);

Template template1 = Template.builder().id(1L).template("test").build();
Template template2 = Template.builder().id(2L).template("TEST2").build();
given(templateRepository.findAll()).willReturn(List.of(template1, template2));

// when, then
assertThatNoException()
.isThrownBy(() -> mailTemplateLoader.run(mock(ApplicationArguments.class)));

}

@Test
void DB에_메일템플릿이_두개가_아닐경우_예외를_발생한다() {
// given
MailTemplateLoader mailTemplateLoader = new MailTemplateLoader(templateRepository);

Template template1 = Template.builder().id(1L).template("test").build();
given(templateRepository.findAll()).willReturn(List.of(template1));

// when, then
assertThrows(MailTemplateException.class, () -> mailTemplateLoader.run(mock(ApplicationArguments.class)));
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.spaceclub.notification.mail.service.event;

import com.spaceclub.notification.mail.service.vo.EventStatusChangeMailInfo;
import com.spaceclub.notification.mail.service.vo.MailInfo;
import com.spaceclub.notification.mail.service.vo.WelcomeMailInfo;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

class MailEventTest {

@Test
void 이메일만으로_웰컴_메일_이벤트_생성에_성공한다() {
// given
String email = "[email protected]";

// when
MailEvent mailEvent = MailEvent.createMailEvent(email);
MailInfo mailInfo = mailEvent.mailInfo();

// then
assertThat(mailInfo).isInstanceOf(WelcomeMailInfo.class);
}

@Test
void 이메일과_클럽이름_이벤트이름_이벤트_상태로_상태변경_이벤트_생성에_성공한다() {
// given
String email = "[email protected]";
String clubName = "Skrrr";
String eventName = "Skrrr Event";
String eventStatus = "CONFIRMED";

// when
MailEvent mailEvent = MailEvent.createMailEvent(email, clubName, eventName, eventStatus);
MailInfo mailInfo = mailEvent.mailInfo();

// then
assertThat(mailInfo).isInstanceOf(EventStatusChangeMailInfo.class);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.spaceclub.notification.mail.service.vo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class ParticipationStatusTest {

@ParameterizedTest
@EnumSource(ParticipationStatus.class)
void 이벤트_상태로_상태_명을_조회하는데_성공한다(ParticipationStatus status) {
// when, then
String statusName = ParticipationStatus.getStatusName(status.name());

assertThatNoException().isThrownBy(() -> ParticipationStatus.getStatusName(status.name()));
assertThat(statusName).isNotEmpty();
}

@Test
void 존재하지_않는_이벤트_상태로_상태명을_조회하면_예외가_발생한다() {
// given
String eventStatus = "NON_EXISTING_STATUS";

// when, then
assertThatThrownBy(() -> ParticipationStatus.getStatusName(eventStatus))
.isInstanceOf(IllegalArgumentException.class);
}

}

0 comments on commit 98efa89

Please sign in to comment.