Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.clokey.domain.like.event;

public record NewLikeEvent(
Long likeId,
Long historyId,
Long receiverId,
Long likerId,
String likerNickname,
String likerProfileImageUrl) {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.clokey.domain.history.repository.HistoryRepository;
import org.clokey.domain.like.dto.response.LikedHistoriesResponse;
import org.clokey.domain.like.dto.response.LikedMembersResponse;
import org.clokey.domain.like.event.NewLikeEvent;
import org.clokey.domain.like.repository.MemberLikeRepository;
import org.clokey.domain.like.repository.MemberLikeRepositoryCustom;
import org.clokey.domain.member.repository.BlockRepository;
Expand Down Expand Up @@ -111,6 +112,14 @@ public void toggleLike(Long historyId) {
} else {
MemberLike newLike = MemberLike.createMemberLike(currentMember, history);
memberLikeRepository.save(newLike);
eventPublisher.publishEvent(
new NewLikeEvent(
newLike.getId(),
history.getId(),
historyOwner.getId(),
currentMember.getId(),
currentMember.getNickname(),
currentMember.getProfileImageUrl()));
}

eventPublisher.publishEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import org.clokey.domain.comment.event.NewCommentEvent;
import org.clokey.domain.comment.event.NewReplyEvent;
import org.clokey.domain.like.event.NewLikeEvent;
import org.clokey.domain.member.event.NewFollowerEvent;
import org.clokey.domain.member.event.NewPendingFollowerEvent;
import org.clokey.domain.notification.service.CodiveNotificationService;
Expand Down Expand Up @@ -84,4 +85,18 @@ public void handleNewReply(NewReplyEvent event) {
e);
}
}

@Async
@TransactionalEventListener(classes = NewLikeEvent.class, phase = TransactionPhase.AFTER_COMMIT)
public void handleNewLike(NewLikeEvent event) {
try {
codiveNotificationService.sendNewLikeNotification(event);
} catch (Exception e) {
log.error(
"새 좋아요 알림 전송 실패 - historyId: {}, likeId: {}",
event.historyId(),
event.likeId(),
e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.clokey.domain.comment.event.NewCommentEvent;
import org.clokey.domain.comment.event.NewReplyEvent;
import org.clokey.domain.like.event.NewLikeEvent;
import org.clokey.domain.notification.dto.request.TemperatureNotificationRequest;
import org.clokey.domain.notification.dto.response.NotificationListResponse;
import org.clokey.domain.notification.dto.response.UnreadNotificationResponse;
Expand All @@ -17,6 +18,8 @@ public interface CodiveNotificationService {

void sendNewReplyNotification(NewReplyEvent event);

void sendNewLikeNotification(NewLikeEvent event);

void sendNewTemperatureNotification(TemperatureNotificationRequest request);

SliceResponse<NotificationListResponse> getNotificationList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.clokey.comment.entitiy.Comment;
import org.clokey.domain.comment.event.NewCommentEvent;
import org.clokey.domain.comment.event.NewReplyEvent;
import org.clokey.domain.comment.exception.CommentErrorCode;
import org.clokey.domain.comment.repository.CommentRepository;
import org.clokey.domain.history.exception.HistoryErrorCode;
import org.clokey.domain.history.repository.HistoryRepository;
import org.clokey.domain.like.event.NewLikeEvent;
import org.clokey.domain.member.exception.MemberErrorCode;
import org.clokey.domain.member.repository.MemberRepository;
import org.clokey.domain.notification.dto.request.TemperatureNotificationRequest;
Expand All @@ -32,9 +34,15 @@
import org.clokey.notification.enums.ReadStatus;
import org.clokey.notification.enums.RedirectType;
import org.clokey.response.SliceResponse;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
Expand All @@ -46,19 +54,22 @@ public class CodiveNotificationServiceImpl implements CodiveNotificationService
private final HistoryRepository historyRepository;
private final CommentRepository commentRepository;
private final FirebaseMessaging firebaseMessaging;
private final ApplicationEventPublisher eventPublisher;

private final MemberUtil memberUtil;

private static final String NEW_FOLLOWER_NOTIFICATION = "%s님이 회원님의 옷장을 팔로우하기 시작했습니다.";
private static final String NEW_PENDING_FOLLOWER_NOTIFICATION = "%s님이 회원님의 옷장에 팔로우를 요청했습니다.";
private static final String NEW_COMMENT_NOTIFICATION = "%s님이 회원님의 기록에 댓글을 남겼습니다. : %s";
private static final String NEW_REPLY_NOTIFICATION = "%s님이 회원님의 댓글에 답장을 남겼습니다. : %s";
private static final String NEW_LIKE_NOTIFICATION = "%s님이 회원님의 기록을 좋아합니다.";

private static final String TODAY_TEMPERATURE_NOTIFICATION =
"오늘의 기온은 %d도 입니다!\n날씨에 맞는 오늘의 옷차림이 기다리고 있어요👀";
private static final String TODAY_TEMPERATURE_IMAGE_URL = "https://example.com/temperature.png";

@Override
@Transactional
public void sendNewFollowerNotification(Long followFromId, Long followToId) {
Member followFromMember = getMemberById(followFromId);
Member followToMember = getMemberById(followToId);
Expand All @@ -80,12 +91,6 @@ public void sendNewFollowerNotification(Long followFromId, Long followToId) {
.putData("redirectType", "MEMBER_PROFILE")
.build();

try {
firebaseMessaging.send(message);
} catch (FirebaseMessagingException e) {
throw new BaseCustomException(NotificationErrorCode.NOTIFICATION_FIREBASE_ERROR);
}

CodiveNotification codiveNotification =
CodiveNotification.createCodiveNotification(
followToMember,
Expand All @@ -96,10 +101,12 @@ public void sendNewFollowerNotification(Long followFromId, Long followToId) {
NotificationType.FOLLOW);

codiveNotificationRepository.save(codiveNotification);
eventPublisher.publishEvent(PushSendEvent.from(message));
}
}

@Override
@Transactional
public void sendNewPendingFollowerNotification(Long followFromId, Long followToId) {
Member followFromMember = getMemberById(followFromId);
Member followToMember = getMemberById(followToId);
Expand All @@ -122,12 +129,6 @@ public void sendNewPendingFollowerNotification(Long followFromId, Long followToI
.putData("redirectType", "MEMBER_PROFILE")
.build();

try {
firebaseMessaging.send(message);
} catch (FirebaseMessagingException e) {
throw new BaseCustomException(NotificationErrorCode.NOTIFICATION_FIREBASE_ERROR);
}

CodiveNotification codiveNotification =
CodiveNotification.createCodiveNotification(
followToMember,
Expand All @@ -138,10 +139,12 @@ public void sendNewPendingFollowerNotification(Long followFromId, Long followToI
NotificationType.FOLLOW_REQUEST);

codiveNotificationRepository.save(codiveNotification);
eventPublisher.publishEvent(PushSendEvent.from(message));
}
}

@Override
@Transactional
public void sendNewCommentNotification(NewCommentEvent event) {

Member receiver = getMemberById(event.receiverId());
Expand All @@ -165,12 +168,6 @@ public void sendNewCommentNotification(NewCommentEvent event) {
.putData("commentId", String.valueOf(event.commentId()))
.putData("commenterId", String.valueOf(event.commenterId()))
.build();

try {
firebaseMessaging.send(message);
} catch (FirebaseMessagingException e) {
throw new BaseCustomException(NotificationErrorCode.NOTIFICATION_FIREBASE_ERROR);
}
CodiveNotification codiveNotification =
CodiveNotification.createCodiveNotification(
receiver,
Expand All @@ -181,10 +178,12 @@ public void sendNewCommentNotification(NewCommentEvent event) {
NotificationType.COMMENT);

codiveNotificationRepository.save(codiveNotification);
eventPublisher.publishEvent(PushSendEvent.from(message));
}
}

@Override
@Transactional
public void sendNewReplyNotification(NewReplyEvent event) {
Member receiver = getMemberById(event.receiverId());

Expand All @@ -205,12 +204,6 @@ public void sendNewReplyNotification(NewReplyEvent event) {
.putData("replierId", String.valueOf(event.replierId()))
.build();

try {
firebaseMessaging.send(message);
} catch (FirebaseMessagingException e) {
throw new BaseCustomException(NotificationErrorCode.NOTIFICATION_FIREBASE_ERROR);
}

CodiveNotification codiveNotification =
CodiveNotification.createCodiveNotification(
receiver,
Expand All @@ -221,10 +214,45 @@ public void sendNewReplyNotification(NewReplyEvent event) {
NotificationType.REPLY);

codiveNotificationRepository.save(codiveNotification);
eventPublisher.publishEvent(PushSendEvent.from(message));
}
}

@Override
@Transactional
public void sendNewLikeNotification(NewLikeEvent event) {
Member receiver = getMemberById(event.receiverId());

if (isAbleToSendNotification(receiver)) {
String content = String.format(NEW_LIKE_NOTIFICATION, event.likerNickname());
String profileImageUrl = event.likerProfileImageUrl();

Notification notification =
Notification.builder().setBody(content).setImage(profileImageUrl).build();
Message message =
Message.builder()
.setToken(receiver.getDeviceToken())
.setNotification(notification)
.putData("historyId", String.valueOf(event.historyId()))
.putData("likerId", String.valueOf(event.likerId()))
.putData("likerNickName", String.valueOf(event.likerNickname()))
.build();
CodiveNotification codiveNotification =
CodiveNotification.createCodiveNotification(
receiver,
content,
profileImageUrl,
event.likerNickname(),
RedirectType.MEMBER_REDIRECT,
NotificationType.LIKE);

codiveNotificationRepository.save(codiveNotification);
eventPublisher.publishEvent(PushSendEvent.from(message));
}
}

@Override
@Transactional
public void sendNewTemperatureNotification(TemperatureNotificationRequest request) {
Member receiver = memberUtil.getCurrentMember();
String content =
Expand All @@ -242,12 +270,6 @@ public void sendNewTemperatureNotification(TemperatureNotificationRequest reques
.setNotification(notification)
.build();

try {
firebaseMessaging.send(message);
} catch (FirebaseMessagingException e) {
throw new BaseCustomException(NotificationErrorCode.NOTIFICATION_FIREBASE_ERROR);
}

CodiveNotification codiveNotification =
CodiveNotification.createCodiveNotification(
receiver,
Expand All @@ -258,6 +280,7 @@ public void sendNewTemperatureNotification(TemperatureNotificationRequest reques
NotificationType.TEMPERATURE_DAILY);

codiveNotificationRepository.save(codiveNotification);
eventPublisher.publishEvent(PushSendEvent.from(message));
}
}

Expand Down Expand Up @@ -342,4 +365,22 @@ private boolean isAbleToSendNotification(Member followToMember) {

return isActive && hasDeviceToken && hasAgreed;
}

@Async
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void sendPushAfterCommit(PushSendEvent event) {
try {
firebaseMessaging.send(event.message());
} catch (FirebaseMessagingException e) {
log.warn("[Notification] Firebase 전송 실패", e);
throw new BaseCustomException(NotificationErrorCode.NOTIFICATION_FIREBASE_ERROR);
}
}

private record PushSendEvent(Message message) {
private static PushSendEvent from(Message message) {
return new PushSendEvent(message);
}
}
}
Loading