Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] 입장 10분 전 푸시 알림 전송 기능 구현 (#483) #484

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
cbcad44
feat: 입장 알림 전송 기능 구현
xxeol2 Oct 1, 2023
21f86ff
refactor: FCMClient 인터페이스화
xxeol2 Oct 2, 2023
4c17ab6
refactor: 스케쥴링 중복 실행시 409 Conflict
xxeol2 Oct 2, 2023
2e4530d
refactor: entryAlert 비관적락 적용
xxeol2 Oct 2, 2023
4a77dd7
refactor: EntryAlertEventListener에서 EntryAlertRepository 참조 제거
xxeol2 Oct 2, 2023
690f90f
refactor: FCM Aycnc Config 정의
xxeol2 Oct 2, 2023
323c6d9
feat: flyway script 작성
xxeol2 Oct 2, 2023
1651604
feat: MockFcmClient 생성
xxeol2 Oct 2, 2023
3b308b5
refactor: FCMNotificationEventListener Async 빈 지정
xxeol2 Oct 2, 2023
97daba8
feat: SpringBoot 실행시 initSchedule
xxeol2 Oct 2, 2023
aa4e530
refactor: Async ThreadPool 하나만 활용하도록 수정
xxeol2 Oct 2, 2023
44ced57
test: FcmClientImplTet 작성
xxeol2 Oct 2, 2023
bd7451b
feat: MemberFcmFixture 정의
xxeol2 Oct 2, 2023
221cac0
refactor: findAllTokenByMemberIdIn 메서드 활용
xxeol2 Oct 2, 2023
a083e3c
style: 패키지 네이밍 수정 (entry_alert -> entryalert)
xxeol2 Oct 2, 2023
6aebcd5
refactor: 500건만 전송하도록 하는 로직 FcmClientImpl로 이동
xxeol2 Oct 4, 2023
da70c4d
refactor: fcmToken String으로 추출
xxeol2 Oct 4, 2023
4c20e30
refactor: ApplicationReadyEvent Listener 최상단으로 이동
xxeol2 Oct 4, 2023
03588d1
refactor: taskScheduler에 람다식으로 넘겨주도록 리팩토링
xxeol2 Oct 4, 2023
64759af
refactor: EntryAlert에 AlertStatus 추가
xxeol2 Oct 4, 2023
a29ae79
refactor: FCM 전송시 데드락 문제 해결
xxeol2 Oct 4, 2023
49c15e6
refactor: AsyncBatch 템플릿 콜백 패턴 적용
xxeol2 Oct 4, 2023
e253317
refactor: Async ThreadPool설정 클래스 위치 이동
xxeol2 Oct 4, 2023
78e5820
refactor: EntryAlertResultHandler 네이밍 수정
xxeol2 Oct 4, 2023
7b4a210
refactor: fcmExecutor QueueCapacity 기본값으로 수정
xxeol2 Oct 4, 2023
fff1325
feat: flyway 추가
xxeol2 Oct 4, 2023
6995f68
test: LocalDateTime 타임존 UTC로 수정
xxeol2 Oct 4, 2023
639e228
Merge remote-tracking branch 'origin/dev' into feat/#483
xxeol2 Oct 5, 2023
ac669fc
fix: EntryAlertServiceTest Mock 객체 수정
xxeol2 Oct 5, 2023
dd9d56f
refactor: test LocalDateTime 수정
xxeol2 Oct 5, 2023
828935c
Merge remote-tracking branch 'origin/dev' into feat/#483
xxeol2 Oct 5, 2023
26fed9f
test: EntryAlertRepositoryTest 작성
xxeol2 Oct 5, 2023
4577784
refactor: JPQL 파라미터 @Param 어노테이션 추가
xxeol2 Oct 5, 2023
44c583b
refactor: 빈 토큰 검사 메서드 네이밍 수정
xxeol2 Oct 5, 2023
a42051a
refactor: SENT/FAILED 상태 삭제
xxeol2 Oct 5, 2023
7d872a9
refcator: EntryAlert 스케쥴링 추가 로깅 자세하게 수정
xxeol2 Oct 5, 2023
310cd14
remove: 불필요한 유틸 클래스 삭제
xxeol2 Oct 5, 2023
ce2adf1
refactor: Test 의존성 추가
xxeol2 Oct 5, 2023
b081b35
refactor: FCmClient로 빈 토큰이 넘어오면 early return
xxeol2 Oct 5, 2023
40f9359
feat: EntryAlert 알림 전송 시작 로깅
xxeol2 Oct 5, 2023
8965022
fix: MockFcmClient Profile 수정
xxeol2 Oct 5, 2023
e374d66
refactor: FcmClientImpl Executor -> TaskExecutor로 수정
xxeol2 Oct 5, 2023
d1f1792
refactor: 접근제어자 변경 public -> private
xxeol2 Oct 5, 2023
6e06a21
refactor: 롬복 적용
xxeol2 Oct 5, 2023
94a3d55
refactor: EntryAlert request상태로 변경 메서드 네이밍 수정
xxeol2 Oct 5, 2023
e45fde3
refactor: sendEntryAlert에서 예외를 던지지 않는 방향으로 수정
xxeol2 Oct 5, 2023
e2b1eaa
refactor: graceful shutdown 설정
xxeol2 Oct 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions backend/src/main/java/com/festago/config/AsyncConfig.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,10 @@
package com.festago.config;

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@EnableAsync
@Configuration
public class AsyncConfig {

private static final String DEFAULT_EXECUTOR_NAME = "taskExecutor";
public static final String FCM_EXECUTOR_NAME = "fcmExecutor";

@Bean(name = DEFAULT_EXECUTOR_NAME)
public Executor defaultExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.initialize();
return executor;
}

@Bean(name = FCM_EXECUTOR_NAME)
public Executor fcmExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setQueueCapacity(10);
executor.initialize();
return executor;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 어떤 맥락에서 추가됐다가 다시 사라진 걸까요 ?_?

Copy link
Member Author

@xxeol2 xxeol2 Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 저희 어플리케이션에서 async 태스크들이 제법 많아졌고, 이벤트 기반으로 수정되며 async 태스크들이 앞으로도 많이 추가될 것으로 예상했는데요

FCM 전송이 500건당 스레드를 하나씩 점유하기때문에, 동시에 많은 사람들에게 FCM을 전송할 경우 다른 async 태스크들도 영향을 받을기에 FCM 스레드풀로 별도로 두는게 좋지않을까? 라는 생각에 분리를 했다가

굳이 지금 그럴 필요는 없을 것 같다는 생각에 롤백했습니다 ㅋㅋㅋ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@async 를 썼을 때 기본적으로 사용하는 스레드 풀 이름이 "taskExecutor" 였군요! overflow
기가 막합니다 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요! 현재는 롤백되었지만.. 2개 이상의 Executor를 Bean으로 등록할때는 "taskExecutor"가 기본적으로 사용됩니다~!
"taskExecutor" 네이밍의 빈이 없을 때는 별도의 Qualifier를 지정하지 않은 경우엔 SimpleAsyncTaskExecutor를 사용하기때문에 주의해야합니다 ㅎㅎ

image
출처: 도둑탈을 쓴 애쉬 ㅋㅋ

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void sendEntryAlert(Long id) {
private void sendMessages(List<String> tokens) {
for (int i = 0; i < tokens.size(); i += BATCH_ALERT_SIZE) {
List<String> subTokens = tokens.subList(i, Math.min(i + BATCH_ALERT_SIZE, tokens.size()));
fcmClient.sendAll(subTokens, FCMChannel.ENTRY_ALERT, FcmPayload.entryAlert());
fcmClient.sendAllAsync(subTokens, FCMChannel.ENTRY_ALERT, FcmPayload.entryAlert());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.festago.fcm.application;

import com.festago.config.AsyncConfig;
import com.festago.entry.dto.event.EntryProcessEvent;
import com.festago.fcm.domain.FCMChannel;
import com.festago.fcm.dto.FcmPayload;
Expand All @@ -23,7 +22,7 @@ public FCMNotificationEventListener(FcmClient fcmClient, MemberFCMService member
}

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
@Async(value = AsyncConfig.FCM_EXECUTOR_NAME)
@Async
public void sendFcmNotification(EntryProcessEvent event) {
List<String> tokens = getMemberFCMToken(event.memberId());
fcmClient.sendAll(tokens, FCMChannel.ENTRY_PROCESS, FcmPayload.entryProcess());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.List;

public interface FcmClient {


void sendAllAsync(List<String> tokens, FCMChannel channel, FcmPayload fcmPayload);

void sendAll(List<String> tokens, FCMChannel channel, FcmPayload fcmPayload);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.festago.fcm.application;

import com.festago.config.AsyncConfig;
import com.festago.fcm.domain.FCMChannel;
import com.festago.fcm.dto.FcmPayload;
import java.util.List;
Expand All @@ -17,7 +16,12 @@ public class MockFcmClient implements FcmClient {
private static final Logger log = LoggerFactory.getLogger(MockFcmClient.class);

@Override
@Async(value = AsyncConfig.FCM_EXECUTOR_NAME)
@Async
public void sendAllAsync(List<String> tokens, FCMChannel channel, FcmPayload fcmPayload) {
sendAll(tokens, channel, fcmPayload);
}

@Override
public void sendAll(List<String> tokens, FCMChannel channel, FcmPayload fcmPayload) {
log.info("[FCM] title: {} / body: {} / to {} device", fcmPayload.title(), fcmPayload.body(), tokens.size());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.festago.common.exception.ErrorCode;
import com.festago.common.exception.InternalServerException;
import com.festago.config.AsyncConfig;
import com.festago.fcm.application.FcmClient;
import com.festago.fcm.domain.FCMChannel;
import com.festago.fcm.dto.FcmPayload;
Expand Down Expand Up @@ -33,7 +32,12 @@ public FcmClientImpl(FirebaseMessaging firebaseMessaging) {
}

@Override
@Async(value = AsyncConfig.FCM_EXECUTOR_NAME)
@Async
public void sendAllAsync(List<String> tokens, FCMChannel channel, FcmPayload fcmPayload) {
sendAll(tokens, channel, fcmPayload);
}

@Override
public void sendAll(List<String> tokens, FCMChannel channel, FcmPayload payload) {
List<Message> messages = createMessages(tokens, channel, payload);
try {
Expand Down