Skip to content

Commit 254ce70

Browse files
authored
Merge pull request #638 from JNU-econovation/feat/#637
[BE/FEAT] Async 스레드 풀 사이즈 조절 및 예외 핸들링외 핸들링 및 ThreadPoolTaskExecutor 값 수정
2 parents acc32b9 + fd1fdf6 commit 254ce70

File tree

8 files changed

+65
-37
lines changed

8 files changed

+65
-37
lines changed

src/main/java/com/gaebaljip/exceed/adapter/out/aws/EmailAdapter.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import com.gaebaljip.exceed.application.port.out.member.EmailPort;
99

1010
import lombok.RequiredArgsConstructor;
11-
import software.amazon.awssdk.services.ses.SesAsyncClient;
11+
import software.amazon.awssdk.services.ses.SesClient;
1212
import software.amazon.awssdk.services.ses.model.*;
1313

1414
@Component
@@ -18,12 +18,11 @@ public class EmailAdapter implements EmailPort {
1818
@Value("${cloud.aws.ses.mail-address}")
1919
private String mailAddress;
2020

21-
private final SesAsyncClient sesAsyncClient;
21+
private final SesClient sesClient;
2222
private final SpringTemplateEngine htmlTemplateEngine;
2323

2424
@Override
2525
public void sendEmail(String to, String title, String template, Context context) {
26-
2726
String html = htmlTemplateEngine.process(template, context);
2827

2928
SendEmailRequest sendEmailRequest =
@@ -33,7 +32,7 @@ public void sendEmail(String to, String title, String template, Context context)
3332
.source(mailAddress)
3433
.build();
3534

36-
sesAsyncClient.sendEmail(sendEmailRequest);
35+
sesClient.sendEmail(sendEmailRequest);
3736
}
3837

3938
private Message newMessage(String subject, String html) {

src/main/java/com/gaebaljip/exceed/common/event/handler/InCompleteSignUpMemberEventListener.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,20 @@ public class InCompleteSignUpMemberEventListener {
2828

2929
private Long expiredTime = 600000L;
3030

31-
@EventListener(classes = IncompleteSignUpEvent.class)
3231
@Async
32+
@EventListener(classes = IncompleteSignUpEvent.class)
3333
public void handle(IncompleteSignUpEvent event) {
3434
int randomCode = createRandom();
3535
codePort.saveWithExpiration(event.getEmail(), String.valueOf(randomCode), expiredTime);
3636
Context context = new Context();
3737
context.setVariable(
3838
MailTemplate.SIGN_UP_MAIL_CONTEXT, URL + MailTemplate.REPLY_TO_SIGN_UP_MAIL_URL);
3939
context.setVariable(MailTemplate.SIGN_UP_CODE, randomCode);
40-
try {
41-
emailPort.sendEmail(
42-
event.getEmail(),
43-
MailTemplate.SIGN_UP_TITLE,
44-
MailTemplate.SIGN_UP_TEMPLATE,
45-
context);
46-
} catch (Exception e) {
47-
log.info("msg : {}", "메일 전송에 실패했습니다.");
48-
codePort.delete(event.getEmail());
49-
}
40+
emailPort.sendEmail(
41+
event.getEmail(),
42+
MailTemplate.SIGN_UP_TITLE,
43+
MailTemplate.SIGN_UP_TEMPLATE,
44+
context);
5045
}
5146

5247
private int createRandom() {

src/main/java/com/gaebaljip/exceed/common/event/handler/SendEmailEventListener.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.gaebaljip.exceed.common.event.handler;
22

33
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.event.EventListener;
45
import org.springframework.scheduling.annotation.Async;
56
import org.springframework.stereotype.Component;
6-
import org.springframework.transaction.annotation.Propagation;
7-
import org.springframework.transaction.annotation.Transactional;
8-
import org.springframework.transaction.event.TransactionalEventListener;
97
import org.thymeleaf.context.Context;
108

119
import com.gaebaljip.exceed.application.domain.member.Code;
@@ -27,9 +25,8 @@ public class SendEmailEventListener {
2725

2826
private Long expiredTime = 600000L;
2927

30-
@TransactionalEventListener(classes = SendEmailEvent.class)
31-
@Transactional(propagation = Propagation.REQUIRES_NEW)
3228
@Async
29+
@EventListener(classes = SendEmailEvent.class)
3330
public void handle(SendEmailEvent event) {
3431
int randomCode = createRandom();
3532
codePort.saveWithExpiration(event.getEmail(), String.valueOf(randomCode), expiredTime);

src/main/java/com/gaebaljip/exceed/common/event/handler/SignUpMemberEventListener.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.gaebaljip.exceed.common.event.handler;
22

33
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.event.EventListener;
45
import org.springframework.scheduling.annotation.Async;
56
import org.springframework.stereotype.Component;
6-
import org.springframework.transaction.annotation.Propagation;
7-
import org.springframework.transaction.annotation.Transactional;
8-
import org.springframework.transaction.event.TransactionalEventListener;
97
import org.thymeleaf.context.Context;
108

119
import com.gaebaljip.exceed.application.domain.member.Code;
@@ -28,9 +26,8 @@ public class SignUpMemberEventListener {
2826

2927
private Long expiredTime = 600000L;
3028

31-
@TransactionalEventListener(classes = SignUpMemberEvent.class)
32-
@Transactional(propagation = Propagation.REQUIRES_NEW)
3329
@Async
30+
@EventListener(classes = SignUpMemberEvent.class)
3431
public void handle(SignUpMemberEvent event) {
3532
int randomCode = createRandom();
3633
codePort.saveWithExpiration(event.getEmail(), String.valueOf(randomCode), expiredTime);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.gaebaljip.exceed.common.exception;
2+
3+
import java.lang.reflect.Method;
4+
import java.util.Arrays;
5+
6+
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
7+
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
@Slf4j
11+
public class EatCeedAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
12+
@Override
13+
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
14+
log.error(
15+
"Exception in async method: {}, Params: {}, Message : {}",
16+
method.getName(),
17+
Arrays.toString(params),
18+
ex.getMessage());
19+
}
20+
}
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package com.gaebaljip.exceed.config;
22

33
import java.util.concurrent.Executor;
4+
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
45

6+
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
57
import org.springframework.context.annotation.Configuration;
68
import org.springframework.context.annotation.Profile;
79
import org.springframework.scheduling.annotation.AsyncConfigurer;
810
import org.springframework.scheduling.annotation.EnableAsync;
911
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
1012

11-
import com.gaebaljip.exceed.common.exception.member.MailSendException;
13+
import com.gaebaljip.exceed.common.exception.EatCeedAsyncUncaughtExceptionHandler;
1214

1315
@EnableAsync
1416
@Configuration
@@ -17,15 +19,17 @@ public class AsyncConfig implements AsyncConfigurer {
1719
@Override
1820
public Executor getAsyncExecutor() {
1921
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
20-
executor.setCorePoolSize(16);
21-
executor.setMaxPoolSize(25);
22+
executor.setCorePoolSize(5);
23+
executor.setMaxPoolSize(15);
2224
executor.setQueueCapacity(10);
23-
executor.setKeepAliveSeconds(60);
24-
executor.setRejectedExecutionHandler(
25-
(r, exec) -> {
26-
throw MailSendException.EXECPTION;
27-
});
25+
executor.setRejectedExecutionHandler(new AbortPolicy());
26+
executor.setWaitForTasksToCompleteOnShutdown(true);
2827
executor.initialize();
2928
return executor;
3029
}
30+
31+
@Override
32+
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
33+
return new EatCeedAsyncUncaughtExceptionHandler();
34+
}
3135
}

src/main/java/com/gaebaljip/exceed/config/SesConfig.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
import org.springframework.beans.factory.annotation.Value;
44
import org.springframework.context.annotation.Bean;
55
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.context.annotation.Profile;
67

78
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
89
import software.amazon.awssdk.regions.Region;
9-
import software.amazon.awssdk.services.ses.SesAsyncClient;
10+
import software.amazon.awssdk.services.ses.SesClient;
1011

1112
@Configuration
13+
@Profile("!test")
1214
public class SesConfig {
1315

1416
@Value("${cloud.aws.credentials.access-key}")
@@ -21,9 +23,8 @@ public class SesConfig {
2123
private String region;
2224

2325
@Bean
24-
public SesAsyncClient sesAsyncClient() {
25-
26-
return SesAsyncClient.builder()
26+
public SesClient sesClient() {
27+
return SesClient.builder()
2728
.credentialsProvider(() -> AwsBasicCredentials.create(accessKey, secretKey))
2829
.region(Region.of(region))
2930
.build();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.gaebaljip.exceed.common;
2+
3+
import org.mockito.Mockito;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
import software.amazon.awssdk.services.ses.SesClient;
8+
9+
@Configuration
10+
public class MockSesConfig {
11+
@Bean
12+
public SesClient sesClient() {
13+
return Mockito.mock(SesClient.class);
14+
}
15+
}

0 commit comments

Comments
 (0)