Skip to content

Commit

Permalink
Merge pull request #210 from Gamegoo-repo/feat/209
Browse files Browse the repository at this point in the history
[Feat/209] 채팅방 목록 조회 API 페이징 추가
  • Loading branch information
Eunjin3395 authored Sep 8, 2024
2 parents aa5c454 + 4530265 commit b6d42ba
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 18 deletions.
7 changes: 5 additions & 2 deletions src/main/java/com/gamegoo/controller/chat/ChatController.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ public ApiResponse<List<String>> getChatroomUuid() {
}

@Operation(summary = "채팅방 목록 조회 API", description = "회원이 속한 채팅방 목록을 조회하는 API 입니다.")
@Parameter(name = "cursor", description = "페이징을 위한 커서, 이전 페이지의 마지막 채팅방의 lastMsgTimestamp입니다. 13자리 timestamp integer를 보내주세요.")
@GetMapping("/member/chatroom")
public ApiResponse<List<ChatResponse.ChatroomViewDTO>> getChatroom() {
public ApiResponse<ChatResponse.ChatroomViewListDTO> getChatroom(
@RequestParam(name = "cursor", required = false) Long cursor
) {
Long memberId = JWTUtil.getCurrentUserId();

return ApiResponse.onSuccess(chatQueryService.getChatroomList(memberId));
return ApiResponse.onSuccess(chatQueryService.getChatroomList(memberId, cursor));
}

@Operation(summary = "특정 회원과 채팅방 시작 API", description = "특정 대상 회원과의 채팅방을 시작하는 API 입니다.\n\n" +
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/com/gamegoo/dto/chat/ChatResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@

public class ChatResponse {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class ChatroomViewListDTO {

List<ChatroomViewDTO> chatroomViewDTOList;
Integer list_size;
Boolean has_next;
Long next_cursor;
}

@Builder
@Getter
@NoArgsConstructor
Expand All @@ -28,6 +40,7 @@ public static class ChatroomViewDTO {
String lastMsg;
String lastMsgAt;
Integer notReadMsgCnt;
Long lastMsgTimestamp;
}

@Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import com.gamegoo.domain.chat.MemberChatroom;
import java.util.List;
import org.springframework.data.domain.Slice;

public interface MemberChatroomRepositoryCustom {

List<MemberChatroom> findActiveMemberChatroomOrderByLastChat(Long memberId);

Slice<MemberChatroom> findActiveMemberChatroomByCursorOrderByLastChat(Long memberId,
Long cursor, Integer pageSize);

List<MemberChatroom> findAllActiveMemberChatroom(Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,45 @@
import static com.gamegoo.domain.chat.QMemberChatroom.memberChatroom;

import com.gamegoo.domain.chat.MemberChatroom;
import com.gamegoo.domain.chat.QChatroom;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Coalesce;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;

@Slf4j
@RequiredArgsConstructor
public class MemberChatroomRepositoryCustomImpl implements MemberChatroomRepositoryCustom {

private final JPAQueryFactory queryFactory;


/**
* 해당 회원의 모든 입장 상태인 채팅방 조회, 해당 채팅방의 마지막 채팅 시각을 기준으로 내림차순 정렬하고, 페이징 포함
*
* @param memberId
* @param cursor
* @param pageSize
* @return
*/
@Override
public List<MemberChatroom> findActiveMemberChatroomOrderByLastChat(Long memberId) {
return queryFactory.selectFrom(memberChatroom)
public Slice<MemberChatroom> findActiveMemberChatroomByCursorOrderByLastChat(Long memberId,
Long cursor, Integer pageSize) {

List<MemberChatroom> result = queryFactory.selectFrom(memberChatroom)
.join(memberChatroom.chatroom, chatroom)
.where(
memberChatroom.member.id.eq(memberId),
memberChatroom.lastJoinDate.isNotNull()
memberChatroom.lastJoinDate.isNotNull(),
lastMsgLessThanCursor(cursor, chatroom)
)
.orderBy(new OrderSpecifier<>(
Order.DESC,
Expand All @@ -41,6 +56,47 @@ public List<MemberChatroom> findActiveMemberChatroomOrderByLastChat(Long memberI
.add(memberChatroom.lastJoinDate) // 해당 채팅방에 대화 내역이 없는 경우, lastJoinDate를 기준으로 정렬
)
)
.limit(pageSize + 1) // 다음 페이지가 있는지 확인하기 위해 +1
.fetch();

boolean hasNext = false;
if (result.size() > pageSize) {
result.remove(pageSize.intValue());
hasNext = true;
}

PageRequest pageRequest = PageRequest.of(0, pageSize);

return new SliceImpl<>(result, pageRequest, hasNext);
}

/**
* 해당 회원의 모든 입장 상태인 채팅방 조회, 정렬 및 페이징 미포함
*
* @param memberId
* @return
*/
@Override
public List<MemberChatroom> findAllActiveMemberChatroom(Long memberId) {
return queryFactory.selectFrom(memberChatroom)
.join(memberChatroom.chatroom, chatroom)
.where(
memberChatroom.member.id.eq(memberId),
memberChatroom.lastJoinDate.isNotNull()
)
.fetch();
}

//--- BooleanExpression ---//
private BooleanExpression lastMsgLessThanCursor(Long cursor, QChatroom chatroom) {
if (cursor == null) {
return null; // null 처리
}

return JPAExpressions.select(chat.timestamp.max())
.from(chat)
.where(
chat.chatroom.eq(chatroom)
).lt(cursor);
}
}
30 changes: 20 additions & 10 deletions src/main/java/com/gamegoo/service/chat/ChatQueryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public class ChatQueryService {
private final ChatRepository chatRepository;
private final ProfileService profileService;
private final FriendService friendService;
private final static int PAGE_SIZE = 20;
private final static int CHAT_PAGE_SIZE = 20;
private final static int PAGE_SIZE = 10;


/**
Expand All @@ -48,19 +49,19 @@ public List<String> getChatroomUuids(Long memberId) {
}

/**
* 채팅방 목록 조회
* 채팅방 목록 조회, 페이징 포함
*
* @param memberId
* @return
*/
public List<ChatResponse.ChatroomViewDTO> getChatroomList(Long memberId) {
public ChatResponse.ChatroomViewListDTO getChatroomList(Long memberId, Long cursor) {
Member member = profileService.findMember(memberId);

// 현재 참여중인 memberChatroom을 각 memberChatroom에 속한 chat의 마지막 createdAt 기준 desc 정렬해 조회
List<MemberChatroom> activeMemberChatroom = memberChatroomRepository.findActiveMemberChatroomOrderByLastChat(
member.getId());
// 현재 참여중인 memberChatroom을 각 memberChatroom에 속한 chat의 마지막 createdAt 기준 desc 정렬해 조회. 페이징 포함
Slice<MemberChatroom> activeMemberChatroom = memberChatroomRepository.findActiveMemberChatroomByCursorOrderByLastChat(
member.getId(), cursor, PAGE_SIZE);

List<ChatResponse.ChatroomViewDTO> chatroomViewDtoList = activeMemberChatroom.stream()
List<ChatResponse.ChatroomViewDTO> chatroomViewDTOList = activeMemberChatroom.stream()
.map(memberChatroom -> {
// 채팅 상대 회원 조회
Member targetMember = memberChatroomRepository.findTargetMemberByChatroomIdAndMemberId(
Expand Down Expand Up @@ -92,12 +93,20 @@ public List<ChatResponse.ChatroomViewDTO> getChatroomList(Long memberId) {
lastChat.get().getCreatedAt())
: DatetimeUtil.toKSTString(memberChatroom.getLastJoinDate()))
.notReadMsgCnt(unReadCnt)
.lastMsgTimestamp(lastChat.isPresent() ? lastChat.get().getTimestamp() : null)
.build();

})
.collect(Collectors.toList());

return chatroomViewDtoList;
// ChatroomViewListDTO 생성
return ChatResponse.ChatroomViewListDTO.builder()
.chatroomViewDTOList(chatroomViewDTOList)
.list_size(chatroomViewDTOList.size())
.has_next(activeMemberChatroom.hasNext())
.next_cursor(activeMemberChatroom.hasNext() ? chatroomViewDTOList.get(
chatroomViewDTOList.size() - 1).getLastMsgTimestamp() : null)
.build();

}

Expand All @@ -122,7 +131,7 @@ public Slice<Chat> getChatMessagesByCursor(String chatroomUuid, Long memberId, L

// 해당 회원이 퇴장한 채팅방은 아닌지도 나중에 검증 추가하기

PageRequest pageRequest = PageRequest.of(0, PAGE_SIZE);
PageRequest pageRequest = PageRequest.of(0, CHAT_PAGE_SIZE);

// requestParam으로 cursor가 넘어온 경우
if (cursor != null) {
Expand All @@ -143,7 +152,8 @@ public Slice<Chat> getChatMessagesByCursor(String chatroomUuid, Long memberId, L
public List<String> getUnreadChatroomUuids(Long memberId) {
Member member = profileService.findMember(memberId);

List<MemberChatroom> activeMemberChatroom = memberChatroomRepository.findActiveMemberChatroomOrderByLastChat(
// 해당 회원의 모든 입장 상태인 채팅방 조회, 정렬 필요 없음
List<MemberChatroom> activeMemberChatroom = memberChatroomRepository.findAllActiveMemberChatroom(
member.getId());

List<String> unreadChatroomUuids = activeMemberChatroom.stream().map(memberChatroom -> {
Expand Down

0 comments on commit b6d42ba

Please sign in to comment.