mirror of
https://github.com/hwanny1128/HGZero.git
synced 2026-06-13 07:09:09 +00:00
feat: 회의예약 시, 이메일발송 기능 보강
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package com.unicorn.hgzero.notification.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* 비동기 처리 설정
|
||||
*
|
||||
* 이메일 발송 등 시간이 오래 걸리는 작업을 비동기로 처리
|
||||
*
|
||||
* @author 준호 (Backend Developer)
|
||||
* @version 1.0
|
||||
* @since 2025-10-26
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
public class AsyncConfig {
|
||||
|
||||
/**
|
||||
* 이메일 발송용 비동기 Executor
|
||||
*
|
||||
* - 코어 스레드: 5개
|
||||
* - 최대 스레드: 10개
|
||||
* - 큐 용량: 100
|
||||
* - 스레드 이름: email-async-
|
||||
*/
|
||||
@Bean(name = "emailTaskExecutor")
|
||||
public Executor emailTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(5);
|
||||
executor.setMaxPoolSize(10);
|
||||
executor.setQueueCapacity(100);
|
||||
executor.setThreadNamePrefix("email-async-");
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(60);
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -62,9 +62,11 @@ public class EventHandler implements Consumer<EventContext> {
|
||||
|
||||
// 토픽 및 이벤트 유형에 따라 처리
|
||||
if ("meeting".equals(topic)) {
|
||||
handleMeetingEvent(eventType, eventBody);
|
||||
log.info("이벤트 처리 제외");
|
||||
// handleMeetingEvent(eventType, eventBody);
|
||||
} else if ("todo".equals(topic)) {
|
||||
handleTodoEvent(eventType, eventBody);
|
||||
log.info("이벤트 처리 제외");
|
||||
// handleTodoEvent(eventType, eventBody);
|
||||
} else if ("notification".equals(topic)) {
|
||||
handleNotificationEvent(eventType, eventBody);
|
||||
} else {
|
||||
|
||||
+11
-7
@@ -8,6 +8,7 @@ import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -28,22 +29,23 @@ public class EmailClient {
|
||||
private final JavaMailSender mailSender;
|
||||
|
||||
/**
|
||||
* HTML 이메일 발송 (재시도 지원)
|
||||
* HTML 이메일 발송 (비동기 + 재시도 지원)
|
||||
*
|
||||
* 발송 실패 시 최대 3번까지 재시도
|
||||
* Exponential Backoff: 초기 5분, 최대 30분, 배수 2.0
|
||||
* Exponential Backoff: 초기 1초, 최대 10초, 배수 2.0
|
||||
*
|
||||
* @param to 수신자 이메일 주소
|
||||
* @param subject 이메일 제목
|
||||
* @param htmlContent HTML 이메일 본문
|
||||
* @throws MessagingException 이메일 발송 실패 시
|
||||
*/
|
||||
@Async("emailTaskExecutor")
|
||||
@Retryable(
|
||||
retryFor = {MessagingException.class},
|
||||
maxAttempts = 3,
|
||||
backoff = @Backoff(
|
||||
delay = 300000, // 5분
|
||||
maxDelay = 1800000, // 30분
|
||||
delay = 1000, // 1초
|
||||
maxDelay = 10000, // 10초
|
||||
multiplier = 2.0
|
||||
)
|
||||
)
|
||||
@@ -57,6 +59,7 @@ public class EmailClient {
|
||||
helper.setTo(to);
|
||||
helper.setSubject(subject);
|
||||
helper.setText(htmlContent, true); // true = HTML 모드
|
||||
// helper.setFrom("du0928@gmail.com");
|
||||
|
||||
mailSender.send(message);
|
||||
|
||||
@@ -69,19 +72,20 @@ public class EmailClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* 텍스트 이메일 발송 (재시도 지원)
|
||||
* 텍스트 이메일 발송 (비동기 + 재시도 지원)
|
||||
*
|
||||
* @param to 수신자 이메일 주소
|
||||
* @param subject 이메일 제목
|
||||
* @param textContent 텍스트 이메일 본문
|
||||
* @throws MessagingException 이메일 발송 실패 시
|
||||
*/
|
||||
@Async("emailTaskExecutor")
|
||||
@Retryable(
|
||||
retryFor = {MessagingException.class},
|
||||
maxAttempts = 3,
|
||||
backoff = @Backoff(
|
||||
delay = 300000,
|
||||
maxDelay = 1800000,
|
||||
delay = 1000, // 1초
|
||||
maxDelay = 10000, // 10초
|
||||
multiplier = 2.0
|
||||
)
|
||||
)
|
||||
|
||||
@@ -49,14 +49,15 @@ spring:
|
||||
password: ${MAIL_PASSWORD:}
|
||||
properties:
|
||||
mail:
|
||||
debug: true
|
||||
smtp:
|
||||
auth: true
|
||||
starttls:
|
||||
enable: true
|
||||
required: true
|
||||
connectiontimeout: 5000
|
||||
timeout: 5000
|
||||
writetimeout: 5000
|
||||
connectiontimeout: 3000
|
||||
timeout: 3000
|
||||
writetimeout: 3000
|
||||
|
||||
# Thymeleaf Configuration
|
||||
thymeleaf:
|
||||
@@ -97,10 +98,11 @@ azure:
|
||||
notification:
|
||||
from-email: ${NOTIFICATION_FROM_EMAIL:noreply@hgzero.com}
|
||||
from-name: ${NOTIFICATION_FROM_NAME:HGZero}
|
||||
retry:
|
||||
max-attempts: ${NOTIFICATION_RETRY_MAX_ATTEMPTS:3}
|
||||
initial-interval: ${NOTIFICATION_RETRY_INITIAL_INTERVAL:1000}
|
||||
multiplier: ${NOTIFICATION_RETRY_MULTIPLIER:2.0}
|
||||
# retry 설정은 EmailClient.java의 @Retryable 어노테이션에서 직접 관리됨
|
||||
# retry:
|
||||
# max-attempts: 3
|
||||
# initial-interval: 1000 # 1초
|
||||
# multiplier: 2.0
|
||||
|
||||
# Actuator Configuration
|
||||
management:
|
||||
|
||||
Reference in New Issue
Block a user