일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 애자일 싫타
- 논블록킹 성능
- 핀포인트
- save/update
- reids
- Loki 로그
- RedirectService
- UnsupportedOperationException
- ㅉ때
- 플루터
- 오블완
- formik
- jsonMarshaller
- pinpoint 2.5.3
- Ingress Controller Fake
- OIDC
- Armeria
- 개발 어렵당.ㅠ
- pinpoint
- 노드간 통신
- 7879
- R2DBC Paging
- nGinder
- 티스토리챌린지
- intellij
- fake jwt
- jar 배포
- LPOS
- 월급루팡 일지
- hbase 저장공간 설정
- Today
- Total
대머리개발자
앱 푸시 - FCM - 조금 고도화 본문
기존 단순하게 테스트를 위해서 진행했던 부분을 고도화
앱 푸시 - FCM
자세한 내용은 해당 블로그에 확인한다. 너무나도 잘 기록되어있다. ㄳhttps://zuminternet.github.io/FCM-PUSH/ FCM 푸시 파헤치기파일럿부터 적용까지 진행했던 FCM 푸시를 파헤치며 기초 가이드북처럼 정
hcnmy.tistory.com
일단 앱 푸쉬를 위한 남들 다하는 카프카는 By Pass 하였다.
많아야 천명 정도에 10개 미만으로 보내는 푸쉬이기 때문에....해보곤 싶었지만 투머취!!
충분히 Flux 만 활용해도 anyway!!
목표 :
1. 실패한 사용자(미설치, 미수신)에겐 문자를 보낸다.
2. 푸쉬에 해당하는 알람을 생성 해야한다. (7일 보관)
미수신 체크가 생각보다 녹록하지 않았고...휘밤
멤버십 가입자에게만 보내는 푸쉬이기 때문에 간단(?)하게 토픽을 이용하려고 했으나...
하나하나 콘트롤 할 수 있도록 토큰으로 방향을 잡았다.
생각보다 많은 포인트에서 짱구를 굴려야 한다.
일단 FCM 푸쉬에 대한 보장을 하지 않는다. 따라서 예외처리가 발생되면 최소 3번을 다시 보낸다. (미수신을 최소화 하자 ㅠ)
그리고 오류가 난 토큰은 계속 에러가 발생하기 때문에 관련 예외가 발생하면 토큰을 삭제 해 준다.
사용자 distinct을 해준 이유는 디바이스가 하나 이상이기 때문에.
....
그냥 모든 것은 코드로 보자.
flatMap과 Map 본질을 느낄수 있는 구문이다..
fcmFlux
.flatMap(fcm -> {
if(Constants.NOT_EXIST.equals(fcm.getToken())){
return Mono.just(Void.TYPE); // 미설치 사용자는 토큰이 없겠쥬.
}
return sendPushMessage(message, fcm.getToken());
})
.then(Mono.delay(Duration.ofSeconds(5))) // 클라이언트가 수신 응답을 싸주는 시간을 넉넉하게 기둘하장.
.thenMany(fcmFlux.distinct(Fcm::getUserUID))
.flatMap( fcm ->
// 클라이언트 정상적인 응답이 없으면 createAlaram을 임의로 만들고 문자 숑숑!
createAlarmIf(MessageAlarm.builder().messageId(message.getId()).userUID(fcm.getUserUID()).build())
.flatMap(isSend -> isSend && (message.getContentType().equalsIgnoreCase(Constants.CLASS) || message.getSendSmsOnPushFailure())? sendTextAfter(buildMessage(message, fcm.getUserUID())) : Mono.empty())
)
.subscribe();
// 중요한게 뭐냐 AI 가 다 만들어준다....첫번째 이미지 처럼 와꾸만 Flow만 생각하고. 디테일한것은. AI 친구에게 맡긴다.
// 근데 이것도 질문이 중요하다.
// 첫번째로는 단순 for 문 돌려서 3번 체크를 했다... 해서 내가 retry 어저꾸 친구가 있는것 같은데.라고 했더니 그제야 다시 바꿔준다. ㅋㅋㅋ 처음 부터 최선을 다하지 않는다. 나쁜놈이 ㅋ
public Mono<Object> sendMessageByToken(MessageGrpc.Message message) {
return Mono.create(sink -> {
try {
...
} catch (FirebaseMessagingException e) {
sink.error(e);
}
})
.onErrorResume(e -> { // retryWhen 밖으로 이동
if (e instanceof FirebaseMessagingException fme){
if(fme.getMessagingErrorCode() == MessagingErrorCode.UNREGISTERED || fme.getMessagingErrorCode() == MessagingErrorCode.INVALID_ARGUMENT){
fcmRepository.deleteFcmByToken(message.getFcmToken()).subscribeOn(Schedulers.boundedElastic()).subscribe();
return Mono.empty(); // 메시지 전송 중단
}
}
return Mono.error(e); // 다른 예외는 다시 throw
})
.retryWhen(Retry.backoff(2, Duration.ofSeconds(1))
.filter(throwable -> throwable instanceof FirebaseMessagingException
&& ((FirebaseMessagingException) throwable).getMessagingErrorCode() != MessagingErrorCode.UNREGISTERED) // UNREGISTERED는 제외
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal) ->
retrySignal.failure()
)
);
}
사요나라...아....AI 학습해야 하는데..
'개발이야기 > 개념' 카테고리의 다른 글
1년이 더해지는 날짜 Formatter 이슈 (0) | 2025.01.03 |
---|---|
앱 푸시 - FCM (0) | 2024.11.27 |
flatMap vs map (1) | 2024.11.20 |
API 호출 vs DB View (0) | 2024.11.11 |
비트 연산은 생각보다 파워풀한 친구다. (0) | 2024.08.19 |