-
Notifications
You must be signed in to change notification settings - Fork 4
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
안 읽은 메시지 카운팅 기능 구현 #709
Merged
Merged
안 읽은 메시지 카운팅 기능 구현 #709
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
96b54d0
feat: 읽은 메시지 로그 도메인 생성
swonny aabc0ef
feat: 읽은 메시지 로그 저장 레포지토리 생성
swonny de9e5e9
refactor: 컬럼명 변경
swonny c773023
feat: 메시지 조회 시 마지막으로 읽은 메시지 로그 저장
swonny ce34598
feat: 채팅방 목록 조회 시 읽지 않은 메시지 개수를 포함하는 기능 추가
swonny d90c03c
feat: 채팅방 생성 시 참여자에 대한 메시지 로그 생성하는 기능 추가
swonny 3f8d431
feat: 경매 아이디로 채팅방 조회하는 기능 추가
swonny e0ef4e8
feat: 채팅방 목록 조회 시 반환값에 안 읽은 메시지 개수 추가
swonny 5e22986
refactor: 메시지 로그 조회 네이밍 변경
swonny b14e7ab
feat: 어노테이션 추가
swonny 049fa04
feat: 로그 찾지 못한 경우에 대한 커스텀 예외 추가
swonny 0e72381
refactor: 로그 생성 로직 이벤트로 분리
swonny 0b1e25c
refactor: 불필요한 메서드 삭제
swonny 066570b
test: 생략한 테스트 추가
swonny b4d03e3
refactor: 채팅방과 메시지 조회 로그cascade type 지정
swonny e7993c6
refactor: 불필요한 파라미터 삭제
swonny 6710648
Merge remote-tracking branch 'origin/develop-be' into feature/677
swonny 824d5c2
feat: flyway 스크립트 작성
swonny a1e3309
refactor: 불필요한 어노테이션 삭제
swonny fbaf37d
refactor: 개행 추가 및 분기문 스트림으로 대체
swonny 35e3b8a
feat: 안 읽은 메시지 개수 컨트롤러 업데이트
swonny 8cc690a
Merge remote-tracking branch 'origin/develop-be' into feature/677
swonny 83aa31c
refactor: 불필요한 필드 삭제
swonny 688d8e2
refactor: 불필요한 join이 발생하는 쿼리 삭제
swonny 591ccd5
refactor: 불필요한 import문 삭제
swonny 3019893
refactor: 메시지 전송과 읽음 저장 트랜잭션 분리
swonny 3bec36d
refactor: 불필요한 어노테이션 삭제, 자동 정렬
swonny 7102287
test: 예외 케이스 테스트 추가
swonny fb80954
Merge remote-tracking branch 'origin/develop-be' into feature/677
swonny dbad4b3
refactor: 업데이트에 적절한 변수명으로 변경
swonny 461d34d
refactor: 레포지토리 저장 시 여러 개 저장하는 메서드 생성
swonny c299d27
chore: 잘못된 flyway 스크림트 수정
swonny File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...ddang/src/main/java/com/ddang/ddang/chat/application/LastReadMessageLogEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.ddang.ddang.chat.application; | ||
|
||
import com.ddang.ddang.chat.application.event.CreateReadMessageLogEvent; | ||
import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; | ||
import com.ddang.ddang.chat.application.exception.ReadMessageLogNotFoundException; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.annotation.Propagation; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.transaction.event.TransactionalEventListener; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class LastReadMessageLogEventListener { | ||
|
||
private final LastReadMessageLogService lastReadMessageLogService; | ||
|
||
@TransactionalEventListener | ||
@Transactional(propagation = Propagation.REQUIRES_NEW) | ||
public void create(final CreateReadMessageLogEvent createReadMessageLogEvent) { | ||
try { | ||
lastReadMessageLogService.create(createReadMessageLogEvent); | ||
} catch (final IllegalArgumentException ex) { | ||
log.error("exception type : {}, ", ex.getClass().getSimpleName(), ex); | ||
} | ||
} | ||
|
||
@TransactionalEventListener | ||
@Transactional(propagation = Propagation.REQUIRES_NEW) | ||
public void update(final UpdateReadMessageLogEvent updateReadMessageLogEvent) { | ||
try { | ||
lastReadMessageLogService.update(updateReadMessageLogEvent); | ||
} catch (final ReadMessageLogNotFoundException ex) { | ||
log.error("exception type : {}, ", ex.getClass().getSimpleName(), ex); | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
backend/ddang/src/main/java/com/ddang/ddang/chat/application/LastReadMessageLogService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.ddang.ddang.chat.application; | ||
|
||
import com.ddang.ddang.chat.application.event.CreateReadMessageLogEvent; | ||
import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; | ||
import com.ddang.ddang.chat.application.exception.ReadMessageLogNotFoundException; | ||
import com.ddang.ddang.chat.domain.ChatRoom; | ||
import com.ddang.ddang.chat.domain.ReadMessageLog; | ||
import com.ddang.ddang.chat.domain.repository.ReadMessageLogRepository; | ||
import com.ddang.ddang.user.domain.User; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
@RequiredArgsConstructor | ||
public class LastReadMessageLogService { | ||
|
||
private final ReadMessageLogRepository readMessageLogRepository; | ||
|
||
@Transactional | ||
public void create(final CreateReadMessageLogEvent createReadMessageLogEvent) { | ||
final ChatRoom chatRoom = createReadMessageLogEvent.chatRoom(); | ||
final User buyer = chatRoom.getBuyer(); | ||
final User seller = chatRoom.getAuction().getSeller(); | ||
final ReadMessageLog buyerReadMessageLog = new ReadMessageLog(chatRoom, buyer); | ||
final ReadMessageLog sellerReadMessageLog = new ReadMessageLog(chatRoom, seller); | ||
|
||
readMessageLogRepository.saveAll(List.of(buyerReadMessageLog, sellerReadMessageLog)); | ||
} | ||
|
||
@Transactional | ||
public void update(final UpdateReadMessageLogEvent updateReadMessageLogEvent) { | ||
final User reader = updateReadMessageLogEvent.reader(); | ||
final ChatRoom chatRoom = updateReadMessageLogEvent.chatRoom(); | ||
final ReadMessageLog messageLog = readMessageLogRepository.findBy(reader.getId(), chatRoom.getId()) | ||
.orElseThrow(() -> | ||
new ReadMessageLogNotFoundException( | ||
"메시지 조회 로그가 존재하지 않습니다." | ||
)); | ||
|
||
messageLog.updateLastReadMessage(updateReadMessageLogEvent.lastReadMessage().getId()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
...ddang/src/main/java/com/ddang/ddang/chat/application/event/CreateReadMessageLogEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.ddang.ddang.chat.application.event; | ||
|
||
import com.ddang.ddang.chat.domain.ChatRoom; | ||
|
||
public record CreateReadMessageLogEvent(ChatRoom chatRoom) { | ||
} |
8 changes: 8 additions & 0 deletions
8
...ddang/src/main/java/com/ddang/ddang/chat/application/event/UpdateReadMessageLogEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.ddang.ddang.chat.application.event; | ||
|
||
import com.ddang.ddang.chat.domain.ChatRoom; | ||
import com.ddang.ddang.chat.domain.Message; | ||
import com.ddang.ddang.user.domain.User; | ||
|
||
public record UpdateReadMessageLogEvent(User reader, ChatRoom chatRoom, Message lastReadMessage) { | ||
} |
8 changes: 8 additions & 0 deletions
8
...main/java/com/ddang/ddang/chat/application/exception/ReadMessageLogNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.ddang.ddang.chat.application.exception; | ||
|
||
public class ReadMessageLogNotFoundException extends IllegalArgumentException { | ||
|
||
public ReadMessageLogNotFoundException(final String message) { | ||
super(message); | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
backend/ddang/src/main/java/com/ddang/ddang/chat/domain/ReadMessageLog.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.ddang.ddang.chat.domain; | ||
|
||
import com.ddang.ddang.user.domain.User; | ||
import jakarta.persistence.CascadeType; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.FetchType; | ||
import jakarta.persistence.ForeignKey; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.JoinColumn; | ||
import jakarta.persistence.ManyToOne; | ||
import jakarta.persistence.OneToOne; | ||
import lombok.AccessLevel; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.ToString; | ||
|
||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Getter | ||
@EqualsAndHashCode(of = "id", callSuper = false) | ||
@ToString(of = {"id", "lastReadMessageId"}) | ||
public class ReadMessageLog { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.REMOVE}) | ||
@JoinColumn(name = "chat_room_id", nullable = false, foreignKey = @ForeignKey(name = "fk_read_message_log_chat_room")) | ||
private ChatRoom chatRoom; | ||
|
||
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.REMOVE}) | ||
@JoinColumn(name = "reader_id", nullable = false, foreignKey = @ForeignKey(name = "fk_read_message_log_reader")) | ||
private User reader; | ||
|
||
private Long lastReadMessageId = 0L; | ||
|
||
public ReadMessageLog(final ChatRoom chatRoom, final User reader) { | ||
this.chatRoom = chatRoom; | ||
this.reader = reader; | ||
} | ||
|
||
public void updateLastReadMessage(final Long lastReadMessageId) { | ||
this.lastReadMessageId = lastReadMessageId; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
.../ddang/src/main/java/com/ddang/ddang/chat/domain/repository/ReadMessageLogRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.ddang.ddang.chat.domain.repository; | ||
|
||
import com.ddang.ddang.chat.domain.ReadMessageLog; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
public interface ReadMessageLogRepository { | ||
|
||
Optional<ReadMessageLog> findBy(final Long readerId, final Long chatRoomId); | ||
|
||
List<ReadMessageLog> saveAll(List<ReadMessageLog> readMessageLogs); | ||
} |
17 changes: 17 additions & 0 deletions
17
...ain/java/com/ddang/ddang/chat/infrastructure/persistence/JpaReadMessageLogRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.ddang.ddang.chat.infrastructure.persistence; | ||
|
||
import com.ddang.ddang.chat.domain.ReadMessageLog; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
|
||
import java.util.Optional; | ||
|
||
public interface JpaReadMessageLogRepository extends JpaRepository<ReadMessageLog, Long> { | ||
|
||
@Query(""" | ||
SELECT rml | ||
FROM ReadMessageLog rml | ||
WHERE rml.chatRoom.id = :chatRoomId AND rml.reader.id = :readerId | ||
""") | ||
Optional<ReadMessageLog> findLastReadMessageByUserIdAndChatRoomId(final Long readerId, final Long chatRoomId); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
import com.ddang.ddang.chat.infrastructure.persistence.dto.QChatRoomAndMessageAndImageQueryProjectionDto; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.jpa.JPAExpressions; | ||
import com.querydsl.jpa.JPQLQuery; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Repository; | ||
|
@@ -15,6 +16,7 @@ | |
import static com.ddang.ddang.auction.domain.QAuction.auction; | ||
import static com.ddang.ddang.chat.domain.QChatRoom.chatRoom; | ||
import static com.ddang.ddang.chat.domain.QMessage.message; | ||
import static com.ddang.ddang.chat.domain.QReadMessageLog.readMessageLog; | ||
import static com.ddang.ddang.image.domain.QAuctionImage.auctionImage; | ||
import static java.util.Comparator.comparing; | ||
|
||
|
@@ -26,8 +28,12 @@ public class QuerydslChatRoomAndMessageAndImageRepository { | |
|
||
public List<ChatRoomAndMessageAndImageDto> findAllChatRoomInfoByUserIdOrderByLastMessage(final Long userId) { | ||
final List<ChatRoomAndMessageAndImageQueryProjectionDto> unsortedDtos = | ||
queryFactory.select(new QChatRoomAndMessageAndImageQueryProjectionDto(chatRoom, message, auctionImage)) | ||
.from(chatRoom) | ||
queryFactory.select(new QChatRoomAndMessageAndImageQueryProjectionDto( | ||
chatRoom, | ||
message, | ||
auctionImage, | ||
countUnreadMessages(userId) | ||
Comment on lines
+31
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 칭찬믿겠습니다....메리... |
||
)).from(chatRoom) | ||
.leftJoin(chatRoom.buyer).fetchJoin() | ||
.leftJoin(chatRoom.auction, auction).fetchJoin() | ||
.leftJoin(auction.seller).fetchJoin() | ||
|
@@ -52,6 +58,21 @@ public List<ChatRoomAndMessageAndImageDto> findAllChatRoomInfoByUserIdOrderByLas | |
return sortByLastMessageIdDesc(unsortedDtos); | ||
} | ||
|
||
private static JPQLQuery<Long> countUnreadMessages(final Long userId) { | ||
return JPAExpressions.select(message.count()) | ||
.from(message) | ||
.where( | ||
message.chatRoom.id.eq(chatRoom.id), | ||
message.writer.id.ne(userId), | ||
message.id.gt( | ||
JPAExpressions | ||
.select(readMessageLog.lastReadMessageId) | ||
.from(readMessageLog) | ||
.where(readMessageLog.reader.id.eq(userId)) | ||
) | ||
); | ||
} | ||
|
||
private List<ChatRoomAndMessageAndImageDto> sortByLastMessageIdDesc( | ||
final List<ChatRoomAndMessageAndImageQueryProjectionDto> unsortedDtos | ||
) { | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
선택
개행..?