Skip to content

Commit

Permalink
feat: 채팅 조회 (#49)
Browse files Browse the repository at this point in the history
feat: 채팅 조회
  • Loading branch information
LJH098 authored Nov 14, 2024
2 parents d195b76 + 3a151b0 commit f1331b6
Show file tree
Hide file tree
Showing 23 changed files with 399 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.hyunsolution.dangu.chatlog;
package com.hyunsolution.dangu.chatlog.domain;

import com.hyunsolution.dangu.user.domain.User;
import com.hyunsolution.dangu.workspace.domain.Workspace;
Expand All @@ -13,7 +13,7 @@
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Chatlog {
public class ChatLog {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down Expand Up @@ -57,16 +57,12 @@ public void read() {
*/

@Builder
private Chatlog(
User user,
Workspace workspace,
LocalDateTime enterTime,
Boolean isOut,
Integer readCount) {
private ChatLog(User user, Workspace workspace, LocalDateTime enterTime, Integer readCount) {
this.user = user;
this.workspace = workspace;
this.enterTime = enterTime;
this.isOut = isOut;
this.readCount = readCount;
this.isOut = false;
this.readCount = 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.hyunsolution.dangu.chatlog.domain;

import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ChatLogRepository extends JpaRepository<ChatLog, Long> {
@Query("select cl from ChatLog cl where cl.workspace.id =:workspaceId and cl.user.id =:userId")
Optional<ChatLog> findByWorkspaceIdAndUserId(Long workspaceId, Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.hyunsolution.dangu.chatlog.exception;

import com.hyunsolution.dangu.common.exception.BaseErrorCode;
import com.hyunsolution.dangu.common.exception.ExceptionDto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum ChatLogError implements BaseErrorCode {
CHAT_LOG_NOT_FOUND("CHAT_LOG_400_1", HttpStatus.BAD_REQUEST, "채팅 기록을 찾을 수 없습니다."),
;
private final String code;
private final HttpStatus httpStatus;
private final String message;

@Override
public ExceptionDto getErrorReason() {
return ExceptionDto.builder().code(code).message(message).httpStatus(httpStatus).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.hyunsolution.dangu.chatlog.exception;

import com.hyunsolution.dangu.common.exception.CustomException;

public class ChatLogNotFoundException extends CustomException {
public static final ChatLogNotFoundException EXCEPTION = new ChatLogNotFoundException();

private ChatLogNotFoundException() {
super(ChatLogError.CHAT_LOG_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
public class ChatController {
private final ChatService chatService;

//채팅기능
// 채팅기능
@MessageMapping("/chat/{chatRoomId}")
@SendTo("/topic/chat/{chatRoomId}")
public ChatMessageResponse sendChatMessage(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.hyunsolution.dangu.chatting.controller;

import com.hyunsolution.dangu.chatting.dto.response.GetChatRoomsResponse;
import com.hyunsolution.dangu.chatting.dto.response.GetChattingsResponse;
import com.hyunsolution.dangu.chatting.service.ChattingService;
import com.hyunsolution.dangu.common.apiResponse.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class ChattingController {
private final ChattingService chattingService;

@GetMapping("/chattings/{chatRoomId}")
@Operation(
summary = "채팅방에 대한 채팅을 조회한다.",
description = "워크스페이스(채팅방)에 대한 채팅을 조회한다. 워크스페이스 당 채팅방 하나 이기 때문에 워크스페이스를 채팅방이랑 같다고 생각")
public ApiResponse<List<GetChattingsResponse>> getChattings(
@Parameter(hidden = true) @RequestHeader("Authorization") Long userId,
@PathVariable Long chatRoomId) {
List<GetChattingsResponse> responses = chattingService.getChattings(userId, chatRoomId);
return ApiResponse.success(responses);
}

@GetMapping("/chattings")
@Operation(summary = "채팅방 목록을 조회한다.", description = "자신이 들어가 있는 채팅방 목록을 조회한다.")
public ApiResponse<List<GetChatRoomsResponse>> getChatRooms(
@Parameter(hidden = true) @RequestHeader("Authorization") Long userId) {
List<GetChatRoomsResponse> responses = chattingService.getChatRooms(userId);
return ApiResponse.success(responses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EntityListeners(AuditingEntityListener.class)
@Table(indexes = {@Index(name = "idx_workspace_id_id", columnList = "workspace_id, id DESC")})
public class Chatting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -32,19 +33,19 @@ public class Chatting {
name = "user_id",
nullable = false,
foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private User user;
private User sender;

@Column( nullable = false)
@Column(nullable = false)
private String content;

@Column(name = "created_at", nullable = false)
@CreatedDate
private LocalDateTime createdAt;

@Builder
private Chatting(Workspace workspace, User user, String content) {
private Chatting(Workspace workspace, User sender, String content) {
this.workspace = workspace;
this.user = user;
this.sender = sender;
this.content = content;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.hyunsolution.dangu.chatting.domain;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ChattingRepository extends JpaRepository<Chatting, Long> {
@Query("select c from Chatting c where c.workspace.id =:workspaceId")
List<Chatting> findByWorkspaceId(Long workspaceId);

@Query(
value =
"select c.content from chatting c where c.id = ("
+ "select MAX(id) from chatting where workspace_id = :workspaceId)",
nativeQuery = true)
String findLastChattingContentByWorkspaceId(Long workspaceId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.hyunsolution.dangu.chatting.dto.response;

import java.util.List;

public record GetChatRoomsResponse(
Long chatRoomId, String lastMessage, List<String> otherPerson, int unReadCount) {
public static GetChatRoomsResponse of(
Long chatRoomId, String lastMessage, List<String> otherPerson, int unReadCount) {
return new GetChatRoomsResponse(chatRoomId, lastMessage, otherPerson, unReadCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.hyunsolution.dangu.chatting.dto.response;

public record GetChattingsResponse(String content, Long chattingId, boolean isOwn) {
public static GetChattingsResponse of(String content, Long chattingId, boolean isOwn) {
return new GetChattingsResponse(content, chattingId, isOwn);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ public enum ChatError implements BaseErrorCode {
private final String message;

@Override
public ExceptionDto getErrorReason(){
public ExceptionDto getErrorReason() {
return ExceptionDto.builder().code(code).message(message).httpStatus(httpStatus).build();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ public ChatMessageDetailResponse sendMessage(Long chatRoomId, String message, Lo
Workspace workspace =
workspaceRepository
.findById(chatRoomId)
.orElseThrow(() ->ChatRoomNotFoundException.EXCEPTION);
.orElseThrow(() -> ChatRoomNotFoundException.EXCEPTION);
User user =
userRepository
.findById(userPk)
.orElseThrow(() -> UserNotFoundException.EXCEPTION);
userRepository.findById(userPk).orElseThrow(() -> UserNotFoundException.EXCEPTION);

Chatting chatMessage =
Chatting.builder().workspace(workspace).user(user).content(message).build();
Chatting.builder().workspace(workspace).sender(user).content(message).build();

chatRepository.save(chatMessage);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.hyunsolution.dangu.chatting.service;

import com.hyunsolution.dangu.chatlog.domain.ChatLog;
import com.hyunsolution.dangu.chatlog.domain.ChatLogRepository;
import com.hyunsolution.dangu.chatlog.exception.ChatLogNotFoundException;
import com.hyunsolution.dangu.chatting.domain.Chatting;
import com.hyunsolution.dangu.chatting.domain.ChattingRepository;
import com.hyunsolution.dangu.chatting.dto.response.GetChatRoomsResponse;
import com.hyunsolution.dangu.chatting.dto.response.GetChattingsResponse;
import com.hyunsolution.dangu.workspace.domain.Workspace;
import com.hyunsolution.dangu.workspace.domain.WorkspaceRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class ChattingService {
private final ChattingRepository chattingRepository;
private final ChatLogRepository chatLogRepository;
private final WorkspaceRepository workspaceRepository;

@Transactional(readOnly = true)
public List<GetChattingsResponse> getChattings(Long loginUserId, Long chatRoomId) {
List<Chatting> chattings = chattingRepository.findByWorkspaceId(chatRoomId);
return chattings.stream()
.map(
chatting -> {
boolean isOwn = isOwn(loginUserId, chatting.getSender().getId());
return GetChattingsResponse.of(
chatting.getContent(), chatting.getId(), isOwn);
})
.toList();
}

@Transactional(readOnly = true)
public List<GetChatRoomsResponse> getChatRooms(Long userId) {
List<Workspace> chatRooms = workspaceRepository.findByParticipantUserId(userId);
return chatRooms.stream()
.filter(chatRoom -> chatRoom.getParticipants().size() > 1)
.map(
chatRoom ->
GetChatRoomsResponse.of(
chatRoom.getId(),
getLastMessage(chatRoom.getId()),
getOtherPerson(chatRoom, userId),
getUnReadCount(chatRoom.getId(), userId)))
.toList();
}

private boolean isOwn(Long loginUserId, Long chattingUserId) {
return loginUserId.equals(chattingUserId);
}

private List<String> getOtherPerson(Workspace chatRoom, Long loginUserId) {
return chatRoom.getParticipants().stream()
.filter(participant -> !participant.getUser().getId().equals(loginUserId))
.map(participant -> participant.getUser().getUid())
.toList();
}

private String getLastMessage(Long chatRoomId) {
return chattingRepository.findLastChattingContentByWorkspaceId(chatRoomId);
}

private int getUnReadCount(Long chatRoomId, Long userId) {
ChatLog chatLog =
chatLogRepository
.findByWorkspaceIdAndUserId(chatRoomId, userId)
.orElseThrow(() -> ChatLogNotFoundException.EXCEPTION);
int total = chattingRepository.findByWorkspaceId(chatRoomId).size();
int read = chatLog.getReadCount();
return total - read;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.hyunsolution.dangu.common.config;

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@EnableAsync
@Configuration
@Profile("!test")
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(16);
executor.setMaxPoolSize(25);
executor.setQueueCapacity(10);
executor.setKeepAliveSeconds(60);
executor.initialize();
return executor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.hyunsolution.dangu.common.event;

import com.hyunsolution.dangu.user.domain.User;
import com.hyunsolution.dangu.workspace.domain.Workspace;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class CreateWorkspaceEvent extends DomainEvent {
private Workspace workspace;
private User user;

public static CreateWorkspaceEvent of(Workspace workspace, User user) {
return new CreateWorkspaceEvent(workspace, user);
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/hyunsolution/dangu/common/event/DomainEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.hyunsolution.dangu.common.event;

import java.time.LocalDateTime;
import lombok.Getter;

@Getter
public class DomainEvent {
private final LocalDateTime publishAt;

public DomainEvent() {
this.publishAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.hyunsolution.dangu.common.event;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EventPublish {}
Loading

0 comments on commit f1331b6

Please sign in to comment.