Skip to content

Commit

Permalink
refactor : 알림 전송 로직을 NotificationService에 위임
Browse files Browse the repository at this point in the history
- sendNotificationToMembers() : 그룹, 알림 받는 사람, 카테고리, 메세지 파라미터로 받아 알림 전송
- 예외 로깅을 알림 속에서 처리
  • Loading branch information
rladmstn committed Nov 6, 2024
1 parent 658cc2c commit a416c3b
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 212 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
import com.gamzabat.algohub.feature.group.studygroup.repository.StudyGroupRepository;
import com.gamzabat.algohub.feature.image.service.ImageService;
import com.gamzabat.algohub.feature.notification.domain.NotificationSetting;
import com.gamzabat.algohub.feature.notification.enums.NotificationMessage;
import com.gamzabat.algohub.feature.notification.exception.CannotFoundNotificationSettingException;
import com.gamzabat.algohub.feature.notification.enums.NotificationCategory;
import com.gamzabat.algohub.feature.notification.repository.NotificationSettingRepository;
import com.gamzabat.algohub.feature.notification.service.NotificationService;
import com.gamzabat.algohub.feature.problem.domain.Problem;
Expand Down Expand Up @@ -142,7 +141,7 @@ public void joinGroupWithCode(User user, String code) {
.build()
);

sendNotification(studyGroup, member);
sendNewMemberNotification(studyGroup, member);

log.info("success to join study group");
}
Expand Down Expand Up @@ -452,27 +451,17 @@ public void editStudyGroupVisibility(User user, EditGroupVisibilityRequest reque
log.info("success to update group visibility ( userId : {} )", user.getId());
}

private void sendNotification(StudyGroup studyGroup, GroupMember newMember) {
List<GroupMember> members = groupMemberRepository.findAllByStudyGroup(studyGroup);

List<String> users = new ArrayList<>();
for (GroupMember member : members) {
if (member.getUser().getId().equals(newMember.getUser().getId()))
continue;

NotificationSetting setting = notificationSettingRepository.findByMember(member)
.orElseThrow(() -> new CannotFoundNotificationSettingException("그룹 멤버의 알림 정보를 조회할 수 없습니다."));

if (setting.isAllNotifications() && setting.isNewMember())
users.add(member.getUser().getEmail());
}
private void sendNewMemberNotification(StudyGroup studyGroup, GroupMember newMember) {
List<GroupMember> members = groupMemberRepository.findAllByStudyGroup(studyGroup)
.stream()
.filter(member -> !member.getId().equals(newMember.getId()))
.toList();

try {
String message = NotificationMessage.NEW_MEMBER_JOINED.format(newMember.getUser().getNickname(),
studyGroup.getName());
notificationService.sendList(users, message, studyGroup, null);
} catch (Exception e) {
log.warn("failed to send notification", e);
}
notificationService.sendNotificationToMembers(
studyGroup,
members,
NotificationCategory.NEW_MEMBER_JOINED,
NotificationCategory.NEW_MEMBER_JOINED.getMessage(newMember.getUser().getNickname())
);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package com.gamzabat.algohub.feature.notification.enums;

public enum NotificationMessage {
public enum NotificationCategory {
PROBLEM_STARTED("[%s] 문제가 시작되었습니다! 지금 도전해보세요!"),
NEW_SOLUTION_POSTED("%s님이 새로운 풀이를 등록했습니다! 풀이를 확인하고 의견을 나눠보세요."),
NEW_MEMBER_JOINED("%s님이 %s 스터디에 합류했습니다!"),
NEW_MEMBER_JOINED("%s님이 스터디에 합류했습니다!"),
NEW_COMMENT_POSTED("%s님이 내 풀이에 코멘트를 남겼습니다! 어떤 리뷰인지 확인해보세요."),
PROBLEM_DEADLINE_REACHED("[%s] 문제의 마감이 얼마 남지 않았습니다! 아직 해결하지 못했다면 지금 도전해보세요!");
PROBLEM_DEADLINE_REACHED("[%s] 문제의 마감이 오늘입니다! 아직 해결하지 못했다면 지금 도전해보세요!");

private final String message;

NotificationMessage(String message) {
NotificationCategory(String message) {
this.message = message;
}

public String format(Object... args) {
public String getMessage(Object... args) {
return String.format(message, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import com.gamzabat.algohub.exception.UserValidationException;
import com.gamzabat.algohub.feature.group.studygroup.domain.GroupMember;
import com.gamzabat.algohub.feature.group.studygroup.domain.StudyGroup;
import com.gamzabat.algohub.feature.group.studygroup.repository.GroupMemberRepository;
import com.gamzabat.algohub.feature.group.studygroup.repository.StudyGroupRepository;
import com.gamzabat.algohub.feature.notification.domain.Notification;
import com.gamzabat.algohub.feature.notification.domain.NotificationSetting;
import com.gamzabat.algohub.feature.notification.dto.GetNotificationResponse;
import com.gamzabat.algohub.feature.notification.enums.NotificationCategory;
import com.gamzabat.algohub.feature.notification.exception.CannotFoundNotificationSettingException;
import com.gamzabat.algohub.feature.notification.repository.EmitterRepositoryImpl;
import com.gamzabat.algohub.feature.notification.repository.NotificationRepository;
import com.gamzabat.algohub.feature.group.studygroup.domain.StudyGroup;
import com.gamzabat.algohub.feature.notification.repository.NotificationSettingRepository;
import com.gamzabat.algohub.feature.user.domain.User;
import com.gamzabat.algohub.feature.user.repository.UserRepository;

Expand All @@ -30,6 +37,9 @@
public class NotificationService {
private final EmitterRepositoryImpl emitterRepository;
private final NotificationRepository notificationRepository;
private final NotificationSettingRepository notificationSettingRepository;
private final StudyGroupRepository studyGroupRepository;
private final GroupMemberRepository groupMemberRepository;
private final UserRepository userRepository;

@Transactional
Expand Down Expand Up @@ -98,8 +108,7 @@ public void send(String receiver, String message, StudyGroup studyGroup, String
);
}

@Transactional
public void sendList(List receiverList, String message, StudyGroup studyGroup, String subContent) {
private void sendList(List receiverList, String message, StudyGroup studyGroup, String subContent) {
List<Notification> notifications = new ArrayList<>();
Map<String, SseEmitter> sseEmitters;
for (int i = 0; i < receiverList.size(); i++) {
Expand Down Expand Up @@ -157,4 +166,33 @@ public void updateIsRead(User user) {
});
log.info("success to read status");
}

@Transactional
public void sendNotificationToMembers(StudyGroup group, List<GroupMember> receiver,
NotificationCategory category, String message) {
List<String> users = new ArrayList<>();
for (GroupMember member : receiver) {
NotificationSetting setting = notificationSettingRepository.findByMember(member)
.orElseThrow(() -> new CannotFoundNotificationSettingException("그룹 멤버의 알림 정보를 조회할 수 없습니다."));

if (setting.isAllNotifications() && isSettingOn(setting, category))
users.add(member.getUser().getEmail());
}

try {
sendList(users, message, group, null);
} catch (Exception e) {
log.warn("failed to send notification", e);
}
}

private boolean isSettingOn(NotificationSetting setting, NotificationCategory category) {
return switch (category) {
case NotificationCategory.PROBLEM_STARTED -> setting.isNewProblem();
case NotificationCategory.PROBLEM_DEADLINE_REACHED -> setting.isDeadlineReached();
case NotificationCategory.NEW_COMMENT_POSTED -> setting.isNewComment();
case NotificationCategory.NEW_MEMBER_JOINED -> setting.isNewMember();
case NotificationCategory.NEW_SOLUTION_POSTED -> setting.isNewSolution();
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@
import com.gamzabat.algohub.feature.group.studygroup.etc.RoleOfGroupMember;
import com.gamzabat.algohub.feature.group.studygroup.repository.GroupMemberRepository;
import com.gamzabat.algohub.feature.group.studygroup.repository.StudyGroupRepository;
import com.gamzabat.algohub.feature.notification.domain.NotificationSetting;
import com.gamzabat.algohub.feature.notification.enums.NotificationMessage;
import com.gamzabat.algohub.feature.notification.exception.CannotFoundNotificationSettingException;
import com.gamzabat.algohub.feature.notification.repository.NotificationSettingRepository;
import com.gamzabat.algohub.feature.notification.enums.NotificationCategory;
import com.gamzabat.algohub.feature.notification.service.NotificationService;
import com.gamzabat.algohub.feature.problem.domain.Problem;
import com.gamzabat.algohub.feature.problem.dto.CreateProblemRequest;
Expand All @@ -57,7 +54,6 @@ public class ProblemService {
private final GroupMemberRepository groupMemberRepository;
private final NotificationService notificationService;
private final RestTemplate restTemplate;
private final NotificationSettingRepository notificationSettingRepository;

@Transactional
public void createProblem(User user, CreateProblemRequest request) {
Expand Down Expand Up @@ -87,7 +83,12 @@ public void createProblem(User user, CreateProblemRequest request) {
.build());

if (request.startDate().equals(LocalDate.now()))
sendProblemNotification(group, title, NotificationMessage.PROBLEM_STARTED);
notificationService.sendNotificationToMembers(
group,
groupMemberRepository.findAllByStudyGroup(group),
NotificationCategory.PROBLEM_STARTED,
NotificationCategory.PROBLEM_STARTED.getMessage(title)
);

log.info("success to create problem");
}
Expand Down Expand Up @@ -263,16 +264,24 @@ public void dailyProblemScheduler() {
private void notifyProblemStartsToday(LocalDate now) {
List<Problem> problems = problemRepository.findAllByStartDate(now);
for (Problem problem : problems) {
sendProblemNotification(problem.getStudyGroup(), problem.getTitle(),
NotificationMessage.PROBLEM_STARTED);
notificationService.sendNotificationToMembers(
problem.getStudyGroup(),
groupMemberRepository.findAllByStudyGroup(problem.getStudyGroup()),
NotificationCategory.PROBLEM_STARTED,
NotificationCategory.PROBLEM_STARTED.getMessage(problem.getTitle())
);
}
}

private void notifyProblemEndsToday(LocalDate now) {
List<Problem> problems = problemRepository.findAllByEndDate(now);
for (Problem problem : problems) {
sendProblemNotification(problem.getStudyGroup(), problem.getTitle(),
NotificationMessage.PROBLEM_DEADLINE_REACHED);
notificationService.sendNotificationToMembers(
problem.getStudyGroup(),
groupMemberRepository.findAllByStudyGroup(problem.getStudyGroup()),
NotificationCategory.PROBLEM_DEADLINE_REACHED,
NotificationCategory.PROBLEM_DEADLINE_REACHED.getMessage(problem.getTitle())
);
}
}

Expand Down Expand Up @@ -346,37 +355,4 @@ private Integer calculateAccuracy(Integer submitMemberCount, Integer correctCoun
private Boolean isInProgress(Problem problem) {
return problem.getEndDate() != null && !LocalDate.now().isAfter(problem.getEndDate());
}

private void sendProblemNotification(StudyGroup group, String title, NotificationMessage problemMessage) {
List<GroupMember> members = groupMemberRepository.findAllByStudyGroup(group);

List<String> users = getMembersEmails(members, problemMessage);

try {
String message = problemMessage.format(title);
notificationService.sendList(users, message, group, null);
} catch (Exception e) {
log.warn("failed to send notification", e);
}
}

private List<String> getMembersEmails(List<GroupMember> members, NotificationMessage notificationMessage) {
List<String> users = new ArrayList<>();
for (GroupMember member : members) {
NotificationSetting setting = notificationSettingRepository.findByMember(member)
.orElseThrow(() -> new CannotFoundNotificationSettingException("그룹 멤버의 알림 정보를 조회할 수 없습니다."));

if (setting.isAllNotifications() && isSettingOn(setting, notificationMessage))
users.add(member.getUser().getEmail());
}
return users;
}

private static boolean isSettingOn(NotificationSetting setting, NotificationMessage message) {
return switch (message) {
case NotificationMessage.PROBLEM_STARTED -> setting.isNewProblem();
case NotificationMessage.PROBLEM_DEADLINE_REACHED -> setting.isDeadlineReached();
default -> false;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
import com.gamzabat.algohub.feature.group.studygroup.exception.GroupMemberValidationException;
import com.gamzabat.algohub.feature.group.studygroup.repository.GroupMemberRepository;
import com.gamzabat.algohub.feature.group.studygroup.repository.StudyGroupRepository;
import com.gamzabat.algohub.feature.notification.domain.NotificationSetting;
import com.gamzabat.algohub.feature.notification.exception.CannotFoundNotificationSettingException;
import com.gamzabat.algohub.feature.notification.repository.NotificationSettingRepository;
import com.gamzabat.algohub.feature.notification.enums.NotificationCategory;
import com.gamzabat.algohub.feature.notification.service.NotificationService;
import com.gamzabat.algohub.feature.problem.domain.Problem;
import com.gamzabat.algohub.feature.problem.repository.ProblemRepository;
Expand All @@ -46,7 +44,6 @@ public class SolutionCommentService implements CommentService<CreateSolutionComm
private final StudyGroupRepository studyGroupRepository;
private final GroupMemberRepository groupMemberRepository;
private final NotificationService notificationService;
private final NotificationSettingRepository notificationSettingRepository;

@Override
@Transactional
Expand All @@ -60,31 +57,22 @@ public void createComment(User user, CreateSolutionCommentRequest request) {
.createdAt(LocalDateTime.now())
.build());

sendNotification(user, request.content(), solution);
sendCommentNotification(user, solution);
log.info("success to create solution comment. commentId: {}, solutionId: {}", comment.getId(),
solution.getId());
}

private void sendNotification(User commenter, String content, Solution solution) {
private void sendCommentNotification(User commenter, Solution solution) {
GroupMember member = groupMemberRepository.findByUserAndStudyGroup(solution.getUser(),
solution.getProblem().getStudyGroup())
.orElseThrow(() -> new GroupMemberValidationException(HttpStatus.NOT_FOUND.value(), "참여하지 않은 스터디 그룹입니다."));
NotificationSetting setting = notificationSettingRepository.findByMember(member)
.orElseThrow(() -> new CannotFoundNotificationSettingException("그룹 멤버의 알림 정보를 조회할 수 없습니다."));

if (!setting.isAllNotifications() || !setting.isNewComment())
return;

String message = content.length() < 35 ? content : content.substring(0, 35) + "...";

try {
notificationService.send(solution.getUser().getEmail(),
commenter.getNickname() + "님이 코멘트를 남겼습니다.",
solution.getProblem().getStudyGroup(),
message);
} catch (Exception e) {
log.info("failed to send comment notification", e);
}

notificationService.sendNotificationToMembers(
solution.getProblem().getStudyGroup(),
List.of(member),
NotificationCategory.NEW_COMMENT_POSTED,
NotificationCategory.NEW_COMMENT_POSTED.getMessage(commenter.getNickname())
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
Expand All @@ -23,9 +22,7 @@
import com.gamzabat.algohub.feature.group.studygroup.exception.GroupMemberValidationException;
import com.gamzabat.algohub.feature.group.studygroup.repository.GroupMemberRepository;
import com.gamzabat.algohub.feature.group.studygroup.repository.StudyGroupRepository;
import com.gamzabat.algohub.feature.notification.domain.NotificationSetting;
import com.gamzabat.algohub.feature.notification.enums.NotificationMessage;
import com.gamzabat.algohub.feature.notification.exception.CannotFoundNotificationSettingException;
import com.gamzabat.algohub.feature.notification.enums.NotificationCategory;
import com.gamzabat.algohub.feature.notification.repository.NotificationSettingRepository;
import com.gamzabat.algohub.feature.notification.service.NotificationService;
import com.gamzabat.algohub.feature.problem.domain.Problem;
Expand Down Expand Up @@ -141,31 +138,17 @@ public void createSolution(CreateSolutionRequest request) {
rankingUpdateService.updateRanking(studyGroup);
}

sendNotification(studyGroup, member.get());
sendNewSolutionNotification(studyGroup, member.get());
}
}

private void sendNotification(StudyGroup group, GroupMember solver) {
List<GroupMember> members = groupMemberRepository.findAllByStudyGroup(group);

List<String> users = new ArrayList<>();
for (GroupMember member : members) {
if (member.getUser().getId().equals(solver.getUser().getId()))
continue;

NotificationSetting setting = notificationSettingRepository.findByMember(member)
.orElseThrow(() -> new CannotFoundNotificationSettingException("그룹 멤버의 알림 정보를 조회할 수 없습니다."));

if (setting.isAllNotifications() && setting.isNewSolution())
users.add(member.getUser().getEmail());
}

try {
String message = NotificationMessage.NEW_SOLUTION_POSTED.format(solver.getUser().getNickname());
notificationService.sendList(users, message, group, null);
} catch (Exception e) {
log.warn("failed to send notification", e);
}
private void sendNewSolutionNotification(StudyGroup group, GroupMember solver) {
notificationService.sendNotificationToMembers(
group,
groupMemberRepository.findAllByStudyGroup(group),
NotificationCategory.NEW_SOLUTION_POSTED,
NotificationCategory.NEW_SOLUTION_POSTED.getMessage(solver.getUser().getNickname())
);
}

private boolean isCorrect(String result) {
Expand Down
Loading

0 comments on commit a416c3b

Please sign in to comment.