Skip to content

Commit

Permalink
Merge pull request #121 from jurumarble/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
alsduq1117 authored Oct 23, 2023
2 parents 03cdad9 + ce6c1e8 commit 4b92822
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 35 deletions.
1 change: 1 addition & 0 deletions src/main/java/co/kr/jurumarble/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void addInterceptors(InterceptorRegistry registry) {
.addPathPatterns("/api/{commentType}/{typeId}/comments/{commentId}/restaurant")
.addPathPatterns("/api/{commentType}/{typeId}/comments/{commentId}/restaurant/{contentId}")
.addPathPatterns("/api/notifications")
.addPathPatterns("/api/notifications/v2")
.addPathPatterns("/api/notifications/subscribe")
.addPathPatterns("/api/reports/votes")
.addPathPatterns("/api/reports/comments")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import co.kr.jurumarble.notification.dto.CreateNotificationRequest;
import co.kr.jurumarble.notification.dto.NotificationDto;
import co.kr.jurumarble.notification.dto.NotificationDtoV1;
import co.kr.jurumarble.notification.service.NotificationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand Down Expand Up @@ -45,11 +46,19 @@ public ResponseEntity<?> sendToAllUsers(@RequestBody @Valid CreateNotificationRe

@Operation(summary = "알림 조회", description = "사용자의 모든 알림 메시지를 조회합니다.")
@GetMapping("")
public ResponseEntity<List<NotificationDtoV1>> getNotificationsV1(@RequestAttribute Long userId) {
List<NotificationDtoV1> notifications = notificationService.getNotificationDtosV1(userId);
return new ResponseEntity(notifications, HttpStatus.OK);
}

@Operation(summary = "알림 조회 v2", description = "사용자의 모든 알림 메시지를 조회합니다.")
@GetMapping("/v2")
public ResponseEntity<List<NotificationDto>> getNotifications(@RequestAttribute Long userId) {
List<NotificationDto> notifications = notificationService.getNotificationDtos(userId);
return new ResponseEntity(notifications, HttpStatus.OK);
}


@Operation(summary = "알림 읽음 처리", description = "사용자가 클릭한 알림을 읽음 처리 합니다.")
@PostMapping("/{notificationId}/read")
public ResponseEntity setNotificationAsRead(@PathVariable Long notificationId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,11 @@ public class Notification extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;
private String content;

private String url;

@Column(nullable = false, name = "is_read")
private Boolean isRead;

@Enumerated(EnumType.STRING)
@Column(nullable = false, name = "notification_type")
private NotificationType notificationType;
Expand All @@ -37,9 +34,10 @@ public class Notification extends BaseTimeEntity {
private User receiver;

@Builder
public Notification(User receiver, NotificationType notificationType, String content, String url, Boolean isRead) {
public Notification(User receiver, NotificationType notificationType, String title, String content, String url, Boolean isRead) {
this.receiver = receiver;
this.notificationType = notificationType;
this.title = title;
this.content = content;
this.url = url;
this.isRead = isRead;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,26 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CreateNotificationRequest {

@Schema(description = "알림 메시지", maxLength = 500)
@Schema(description = "알림 제목")
private String title;

@Schema(description = "알림 내용")
private String message;

@Schema(description = "Related Url")
private String relatedUrl;


@Builder
public CreateNotificationRequest(String message, String relatedUrl) {
public CreateNotificationRequest(String title, String message, String relatedUrl) {
this.title = title;
this.message = message;
this.relatedUrl = relatedUrl;
}

public CreateNotificationServiceRequest toServiceRequest() {
return CreateNotificationServiceRequest.builder()
.title(title)
.message(message)
.relatedUrl(relatedUrl)
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
package co.kr.jurumarble.notification.dto;

import co.kr.jurumarble.notification.domain.Notification;
import lombok.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class NotificationDto {
Long id;

String title;
String url;

String content;

Notification.NotificationType type;

Boolean isRead;

LocalDateTime createdAt;

@Builder
public NotificationDto(Long id, String url, String content, Notification.NotificationType type, Boolean isRead, LocalDateTime createdAt) {
public NotificationDto(Long id, String title, String url, String content, Notification.NotificationType type, Boolean isRead, LocalDateTime createdAt) {
this.id = id;
this.title = title;
this.url = url;
this.content = content;
this.type = type;
Expand All @@ -34,6 +34,7 @@ public NotificationDto(Long id, String url, String content, Notification.Notific
public static NotificationDto from(Notification notification) {
return NotificationDto.builder()
.id(notification.getId())
.title(notification.getTitle())
.url(notification.getUrl())
.content(notification.getContent())
.type(notification.getNotificationType())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package co.kr.jurumarble.notification.dto;

import co.kr.jurumarble.notification.domain.Notification;
import lombok.*;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class NotificationDtoV1 {
Long id;

String url;

String content;

Notification.NotificationType type;

Boolean isRead;

LocalDateTime createdAt;

@Builder
public NotificationDtoV1(Long id, String url, String content, Notification.NotificationType type, Boolean isRead, LocalDateTime createdAt) {
this.id = id;
this.url = url;
this.content = content;
this.type = type;
this.isRead = isRead;
this.createdAt = createdAt;
}


public static NotificationDtoV1 from(Notification notification) {
return NotificationDtoV1.builder()
.id(notification.getId())
.url(notification.getUrl())
.content(notification.getContent())
.type(notification.getNotificationType())
.isRead(notification.getIsRead())
.createdAt(notification.getCreatedDate()).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

@Getter
public class CreateNotificationServiceRequest {
private String title;

private String message;

private String relatedUrl;

@Builder
public CreateNotificationServiceRequest(String message, String relatedUrl) {
public CreateNotificationServiceRequest(String title, String message, String relatedUrl) {
this.title = title;
this.message = message;
this.relatedUrl = relatedUrl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,34 +46,33 @@ public void handleDoVote(DoVoteEvent event) {
public void sendNotificationForNewComments(Long voteId) {
Vote vote = voteRepository.findById(voteId).orElseThrow(VoteNotFoundException::new);
User receiver = userRepository.findById(vote.getPostedUserId()).orElseThrow(UserNotFoundException::new);
String content = "[" + vote.getTitle() + "] " + "투표에 댓글이 달렸습니다.";
String title = vote.getTitle();
String content = "투표에 댓글이 달렸습니다.";
String url = String.valueOf(voteId);
notificationService.send(receiver, Notification.NotificationType.COMMENT, content, url);
notificationService.send(receiver, Notification.NotificationType.COMMENT, title, content, url);
log.info("Thread: {}, Notification sent to user: {}, type: {}, content: {}, url: {}",
Thread.currentThread().getName(),
receiver.getId(),
Notification.NotificationType.COMMENT,
content, url);
Thread.currentThread().getName(), receiver.getId(), Notification.NotificationType.COMMENT, title, content, url);
}

public void sendNotificationsForVoters(Long voteId) {
Vote vote = voteRepository.findById(voteId).orElseThrow(VoteNotFoundException::new);
Long count = voteResultRepository.countByVoteId(voteId);
if (count % 10 == 0 && count != 0) {
String content = "[" + vote.getTitle() + "] " + "투표에 " + count + "명 이상이 참여했어요!";
String title = vote.getTitle();
String content = "투표에 " + count + "명 이상이 참여했어요!";
String url = String.valueOf(voteId);
List<VoteResult> voteResultList = voteResultRepository.findByVoteId(voteId);
sendNotificationsToVoters(content, url, voteResultList);
sendNotificationsToVoters(title, content, url, voteResultList);
}
}

private void sendNotificationsToVoters(String content, String url, List<VoteResult> voteResultList) {
private void sendNotificationsToVoters(String title, String content, String url, List<VoteResult> voteResultList) {
for (VoteResult result : voteResultList) {
CompletableFuture.runAsync(() -> {
User receiver = userRepository.findById(result.getVotedUserId()).orElseThrow(UserNotFoundException::new);
notificationService.send(receiver, Notification.NotificationType.VOTE, content, url);
notificationService.send(receiver, Notification.NotificationType.VOTE, title, content, url);
log.info("Thread: {}, Notification sent to user: {}, type: {}, content: {}, url: {}",
Thread.currentThread().getName(), receiver.getId(), Notification.NotificationType.COMMENT, content, url);
Thread.currentThread().getName(), receiver.getId(), Notification.NotificationType.COMMENT, title, content, url);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import co.kr.jurumarble.exception.user.UserNotFoundException;
import co.kr.jurumarble.notification.domain.Notification;
import co.kr.jurumarble.notification.dto.NotificationDto;
import co.kr.jurumarble.notification.dto.NotificationDtoV1;
import co.kr.jurumarble.notification.repository.EmitterRepository;
import co.kr.jurumarble.notification.repository.NotificationRepository;
import co.kr.jurumarble.user.domain.User;
Expand Down Expand Up @@ -46,15 +47,15 @@ public SseEmitter subscribe(Long userId, String lastEventId) {
}

@Transactional
public void send(User receiver, Notification.NotificationType notificationType, String content, String url) {
Notification notification = notificationRepository.save(createNotification(receiver, notificationType, content, url));
public void send(User receiver, Notification.NotificationType notificationType, String title, String content, String url) {
Notification notification = notificationRepository.save(createNotification(receiver, notificationType, title, content, url));
String receiverId = String.valueOf(receiver.getId());
String eventId = receiverId + "_" + System.currentTimeMillis();
Map<String, SseEmitter> emitters = emitterRepository.findAllEmitterStartWithByUserId(receiverId);
emitters.forEach(
(key, emitter) -> {
emitterRepository.saveEventCache(key, notification);
sendNotification(emitter, eventId, key, NotificationDto.from(notification));
sendNotification(emitter, eventId, key, NotificationDtoV1.from(notification));
}
);
}
Expand Down Expand Up @@ -88,10 +89,11 @@ private void sendLostData(String lastEventId, Long userId, String emitterId, Sse
.forEach(entry -> sendNotification(emitter, entry.getKey(), emitterId, entry.getValue()));
}

private Notification createNotification(User receiver, Notification.NotificationType notificationType, String content, String url) {
private Notification createNotification(User receiver, Notification.NotificationType notificationType, String title, String content, String url) {
return Notification.builder()
.receiver(receiver)
.notificationType(notificationType)
.title(title)
.content(content)
.url(url)
.isRead(false)
Expand All @@ -102,26 +104,34 @@ public void sendNotificationToUser(Long receiverId, Long adminId, CreateNotifica
validateAdminId(adminId);
User receiver = userRepository.findById(receiverId).orElseThrow(UserNotFoundException::new);
Notification.NotificationType type = Notification.NotificationType.ADMIN_NOTIFY;
String title = request.getTitle();
String message = request.getMessage();
String relatedUrl = request.getRelatedUrl();
send(receiver, type, message, relatedUrl);
send(receiver, type, title, message, relatedUrl);
}

public void sendNotificationToAllUsers(Long adminId, CreateNotificationServiceRequest request) {
validateAdminId(adminId);
List<User> allUsers = userRepository.findAll();
Notification.NotificationType type = Notification.NotificationType.ADMIN_NOTIFY;
String title = request.getTitle();
String message = request.getMessage();
String relatedUrl = request.getRelatedUrl();

allUsers.stream()
.forEach(user -> CompletableFuture.runAsync(() -> sendAsync(user, type, message, relatedUrl)));
.forEach(user -> CompletableFuture.runAsync(() -> sendAsync(user, type, title, message, relatedUrl)));
}

private void sendAsync(User receiver, Notification.NotificationType notificationType, String content, String relatedUrl) {
send(receiver, notificationType, content, relatedUrl);
private void sendAsync(User receiver, Notification.NotificationType notificationType, String title, String content, String relatedUrl) {
send(receiver, notificationType, title, content, relatedUrl);
log.info("Thread: {}, Notification sent to user: {}, type: {}, content: {}, url: {}",
Thread.currentThread().getName(), receiver.getId(), Notification.NotificationType.COMMENT, content, relatedUrl);
Thread.currentThread().getName(), receiver.getId(), Notification.NotificationType.COMMENT, title, content, relatedUrl);
}

public List<NotificationDtoV1> getNotificationDtosV1(Long userId) {
return getNotificationsByUserId(userId).stream()
.map(NotificationDtoV1::from)
.collect(Collectors.toList());
}

public List<NotificationDto> getNotificationDtos(Long userId) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ CREATE TABLE notification
(
id BIGINT NOT NULL AUTO_INCREMENT,
user_id BIGINT NOT NULL,
title VARCHAR(60) DEFAULT NULL,
content VARCHAR(255) DEFAULT NULL,
url VARCHAR(500) DEFAULT NULL,
is_read BOOLEAN NOT NULL,
Expand Down

0 comments on commit 4b92822

Please sign in to comment.