Skip to content

Commit

Permalink
Merge pull request #139 from Re-4aliens/develop
Browse files Browse the repository at this point in the history
2024-07-30 [Release Note]
  • Loading branch information
coke98 authored Jul 30, 2024
2 parents 8ed2d9e + 4c02138 commit 31888e4
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
package com.aliens.backend.chat.controller.dto.event;

import com.aliens.backend.chat.service.model.MemberPair;

import java.util.Set;

public record ChatRoomExpireEvent(Set<MemberPair> matchedPairs) {
public record ChatRoomExpireEvent() {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.aliens.backend.chat.domain;

public enum ChatRoomStatus {
WAITING, OPEN, CLOSE, BLOCKED;
WAITING, OPENED, CLOSED, BLOCKED;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.aliens.backend.chat.domain.ChatRoom;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

Expand All @@ -11,4 +12,8 @@
public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long> {
@Query("SELECT c FROM ChatRoom c JOIN c.participants p WHERE p.member.id = :memberId")
List<ChatRoom> findByMemberId(Long memberId);

@Modifying
@Query("UPDATE ChatRoom c SET c.status = com.aliens.backend.chat.domain.ChatRoomStatus.CLOSED")
void expireAllChatRooms();
}
19 changes: 18 additions & 1 deletion src/main/java/com/aliens/backend/chat/service/ChatService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import com.aliens.backend.auth.domain.repository.MemberRepository;
import com.aliens.backend.chat.controller.dto.event.ChatRoomBlockEvent;
import com.aliens.backend.chat.controller.dto.event.ChatRoomCreationEvent;
import com.aliens.backend.chat.controller.dto.event.ChatRoomExpireEvent;
import com.aliens.backend.chat.controller.dto.request.MessageSendRequest;
import com.aliens.backend.chat.controller.dto.request.ReadRequest;
import com.aliens.backend.chat.controller.dto.response.ChatSummaryResponse;
import com.aliens.backend.chat.controller.dto.response.ReadResponse;
import com.aliens.backend.chat.domain.ChatParticipant;
import com.aliens.backend.chat.domain.ChatRoom;
import com.aliens.backend.chat.domain.Message;
import com.aliens.backend.chat.domain.repository.ChatParticipantRepository;
import com.aliens.backend.chat.domain.repository.ChatRoomRepository;
import com.aliens.backend.chat.domain.repository.MessageRepository;
import com.aliens.backend.chat.service.model.ChatMessageSummary;
Expand All @@ -21,6 +23,7 @@
import com.aliens.backend.global.response.error.MemberError;
import com.aliens.backend.global.response.success.ChatSuccess;
import com.aliens.backend.notification.domain.FcmTokenRepository;
import jakarta.transaction.Transactional;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessagingTemplate;
Expand All @@ -37,19 +40,22 @@ public class ChatService {
private final FcmTokenRepository fcmTokenRepository;
private final MemberRepository memberRepository;
private final ApplicationEventPublisher eventPublisher;
private final ChatParticipantRepository chatParticipantRepository;

public ChatService(final MessageRepository messageRepository,
final SimpMessagingTemplate messagingTemplate,
final ChatRoomRepository chatRoomRepository,
final FcmTokenRepository fcmTokenRepository,
final MemberRepository memberRepository,
final ApplicationEventPublisher eventPublisher) {
final ApplicationEventPublisher eventPublisher,
final ChatParticipantRepository chatParticipantRepository) {
this.messageRepository = messageRepository;
this.messagingTemplate = messagingTemplate;
this.chatRoomRepository = chatRoomRepository;
this.fcmTokenRepository = fcmTokenRepository;
this.memberRepository = memberRepository;
this.eventPublisher = eventPublisher;
this.chatParticipantRepository = chatParticipantRepository;
}

public String sendMessage(MessageSendRequest messageSendRequest) {
Expand Down Expand Up @@ -154,6 +160,17 @@ private void blockChatRoom(Long chatRoomId) {
chatRoomRepository.save(chatRoom);
}

@EventListener
@Transactional
public void handleChatRoomExpireEvent(ChatRoomExpireEvent chatRoomExpireEvent) {
expireAllChatRooms();
}

private void expireAllChatRooms() {
chatRoomRepository.expireAllChatRooms();
chatParticipantRepository.deleteAll();
}

private ChatRoom findChatRoomsById(final Long chatRoomId) {
return chatRoomRepository.findById(chatRoomId).orElseThrow(() -> new RestApiException(ChatError.CHAT_ROOM_NOT_FOUND));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import com.aliens.backend.chat.domain.ChatRoom;
import com.aliens.backend.chat.service.ChatAuthValidator;
import com.aliens.backend.global.property.WebSocketProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
Expand All @@ -23,8 +21,6 @@ public class ChatChannelInterceptor implements ChannelInterceptor {

private final ChatAuthValidator chatAuthValidator;
private final WebSocketProperties properties;
private final Logger logger = LoggerFactory.getLogger("웹소켓 요청");

private MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();

public ChatChannelInterceptor(ChatAuthValidator chatAuthValidator, WebSocketProperties properties) {
Expand All @@ -35,7 +31,6 @@ public ChatChannelInterceptor(ChatAuthValidator chatAuthValidator, WebSocketProp
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
logger.info("preSend: {} - {}",accessor.getCommand(), accessor.getDestination());

List<ChatRoom> chatRooms = (List<ChatRoom>) accessor.getSessionAttributes().get("chatRooms");
if (StompCommand.SUBSCRIBE.equals(accessor.getCommand())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.aliens.backend.auth.domain.Member;
import com.aliens.backend.block.domain.Block;
import com.aliens.backend.block.domain.repository.BlockRepository;
import com.aliens.backend.chat.controller.dto.event.ChatRoomExpireEvent;
import com.aliens.backend.chat.domain.ChatParticipant;
import com.aliens.backend.chat.domain.ChatRoom;
import com.aliens.backend.chat.domain.repository.ChatParticipantRepository;
Expand Down Expand Up @@ -94,10 +95,9 @@ private MatchingApplication findMatchedMemberApplicationByRoundAndMemberId(Match
@Scheduled(cron = "${matching.round.end}")
@Transactional
public void expireMatching() {
List<MatchingResult> previousMatchingResults = getPreviousMatchingResults();
List<MatchingApplication> previousMatchingApplications = getPreviousMatchingApplications();
previousMatchingApplications.forEach(MatchingApplication::expireMatch);
eventPublisher.expireChatRoom(previousMatchingResults);
eventPublisher.expireChatRoom();
}

private void saveMatchingResult(final MatchingRound matchingRound, final List<Participant> participants) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.aliens.backend.chat.controller.dto.event.ChatRoomExpireEvent;
import com.aliens.backend.chat.service.model.MemberPair;
import com.aliens.backend.mathcing.business.model.Participant;
import com.aliens.backend.mathcing.domain.MatchingResult;
import com.aliens.backend.mathcing.service.model.MatchingNotificationMessage;
import com.aliens.backend.mathcing.service.model.MemberPairGroup;
import com.google.firebase.messaging.MulticastMessage;
Expand All @@ -28,10 +27,8 @@ public void createChatRoom(List<Participant> participants) {
eventPublisher.publishEvent(new ChatRoomCreationEvent(matchedMemberPairs));
}

public void expireChatRoom(List<MatchingResult> matchingResults) {
MemberPairGroup expiredMemberPairGroup = MemberPairGroup.fromMatchingResults(matchingResults);
Set<MemberPair> expiredMemberPairs = expiredMemberPairGroup.getMemberPairs();
eventPublisher.publishEvent(new ChatRoomExpireEvent(expiredMemberPairs));
public void expireChatRoom() {
eventPublisher.publishEvent(new ChatRoomExpireEvent());
}

public void sendNotification(List<Participant> participants) {
Expand Down
7 changes: 7 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ spring:
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
defer-datasource-initialization: true

profiles:
include: secret, matching

logging:
level:
org.springframework.web.socket.config.WebSocketMessageBrokerStats: ERROR

websocket:
port: 8080
endpoint: /ws
topic: /room
request: /chat


45 changes: 24 additions & 21 deletions src/test/java/com/aliens/backend/chatting/socket/WebSocketTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.util.ArrayList;
import java.util.List;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.awaitility.Awaitility.await;
import static org.mockito.Mockito.*;

class WebSocketTest extends BaseIntegrationTest {
Expand Down Expand Up @@ -69,13 +71,14 @@ void WebSocketMessageSendingAndReceiving() throws Exception {
chatClient.connect(accessToken);
List<Object> receiveMessage = chatClient.subscribe(authorizedRoomId);
chatClient.send(properties.getAppDestinationPrefix() + "/send", messageSendRequest);
await().atMost(5, SECONDS).until(() -> !receiveMessage.isEmpty());

//Then
verify(chatService, timeout(100).times(1)).sendMessage(messageSendRequest);
verify(chatChannelInterceptor, timeout(100).times(3)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND
verify(chatService, timeout(100).times(1)).getChatRooms(member.getId()); // CONNECT
verify(chatAuthValidator, timeout(100).times(1)).validateRoomFromTopic(any(), any()); // SUBSCRIBE
verify(chatAuthValidator, timeout(100).times(1)).validateRoom(any(), any()); // SEND
verify(chatService, timeout(20000).times(1)).sendMessage(messageSendRequest);
verify(chatChannelInterceptor, timeout(20000).times(3)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND
verify(chatService, timeout(20000).times(1)).getChatRooms(member.getId()); // CONNECT
verify(chatAuthValidator, timeout(20000).times(1)).validateRoomFromTopic(any(), any()); // SUBSCRIBE
verify(chatAuthValidator, timeout(20000).times(1)).validateRoom(any(), any()); // SEND
Message receivedMessage = objectMapper.readValue((byte[]) receiveMessage.get(0), Message.class);
Assertions.assertEquals(1, receiveMessage.size());
Assertions.assertEquals(expectedMessage.getId(), receivedMessage.getId());
Expand All @@ -99,10 +102,10 @@ void WebSocketSendMessageWithUnauthorizedRoom() throws Exception {
chatClient.send(properties.getAppDestinationPrefix() + "/send", messageSendRequest);

//Then
verify(chatChannelInterceptor, timeout(100).times(4)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND, 4. DISCONNECT
verify(chatService, timeout(100).times(1)).getChatRooms(member.getId());
verify(chatAuthValidator, timeout(100).times(1)).validateRoom(any(), any());
verify(chatController, timeout(100).times(0)).sendMessage(messageSendRequest); // 호출되지 않음
verify(chatChannelInterceptor, timeout(20000).times(4)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND, 4. DISCONNECT
verify(chatService, timeout(20000).times(1)).getChatRooms(member.getId());
verify(chatAuthValidator, timeout(20000).times(1)).validateRoom(any(), any());
verify(chatController, timeout(20000).times(0)).sendMessage(messageSendRequest); // 호출되지 않음
}

@Test
Expand All @@ -116,9 +119,9 @@ void WebSocketSubscribeWithUnauthorizedRoom() throws Exception {
chatClient.subscribe(unAuthorizedRoomId);

//Then
verify(chatChannelInterceptor, timeout(100).times(3)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. DISCONNECT
verify(chatService, timeout(100).times(1)).getChatRooms(member.getId());
verify(chatAuthValidator, timeout(100).times(1)).validateRoomFromTopic(any(), any());
verify(chatChannelInterceptor, timeout(20000).times(3)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. DISCONNECT
verify(chatService, timeout(20000).times(1)).getChatRooms(member.getId());
verify(chatAuthValidator, timeout(20000).times(1)).validateRoomFromTopic(any(), any());
}

@Test
Expand All @@ -135,11 +138,11 @@ void WebSocketReadMessage() throws Exception {
chatClient.send(properties.getAppDestinationPrefix() + "/read", readRequest);

//Then
verify(chatChannelInterceptor, timeout(100).times(3)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND
verify(chatController, timeout(100).times(1)).readMessage(readRequest);
verify(chatService, timeout(100).times(1)).getChatRooms(member.getId()); // CONNECT
verify(chatAuthValidator, timeout(100).times(1)).validateRoomFromTopic(any(), any()); // SUBSCRIBE
verify(chatAuthValidator, timeout(100).times(1)).validateRoom(any(), any()); // SEND
verify(chatChannelInterceptor, timeout(20000).times(3)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND
verify(chatController, timeout(20000).times(1)).readMessage(readRequest);
verify(chatService, timeout(20000).times(1)).getChatRooms(member.getId()); // CONNECT
verify(chatAuthValidator, timeout(20000).times(1)).validateRoomFromTopic(any(), any()); // SUBSCRIBE
verify(chatAuthValidator, timeout(20000).times(1)).validateRoom(any(), any()); // SEND
ReadResponse receivedReadResponse = objectMapper.readValue((byte[]) receiveMessage.get(0), ReadResponse.class);
Assertions.assertEquals(1, receiveMessage.size());
Assertions.assertEquals(readResponse.readBy(), receivedReadResponse.readBy());
Expand All @@ -159,10 +162,10 @@ void WebSocketReadMessageWithUnauthorizedRoom() throws Exception {
chatClient.send(properties.getAppDestinationPrefix() + "/read", unAuthorizedReadRequest);

//Then
verify(chatChannelInterceptor, timeout(100).times(4)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND, 4. DISCONNECT
verify(chatService, timeout(100).times(1)).getChatRooms(member.getId());
verify(chatAuthValidator, timeout(100).times(1)).validateRoom(any(), any());
verify(chatController, timeout(100).times(0)).readMessage(unAuthorizedReadRequest); // 호출되지 않음
verify(chatChannelInterceptor, timeout(20000).times(4)).preSend(any(), any()); // 1. CONNECT, 2. SUBSCRIBE, 3. SEND, 4. DISCONNECT
verify(chatService, timeout(20000).times(1)).getChatRooms(member.getId());
verify(chatAuthValidator, timeout(20000).times(1)).validateRoom(any(), any());
verify(chatController, timeout(20000).times(0)).readMessage(unAuthorizedReadRequest); // 호출되지 않음
}

private MessageSendRequest createMessageSendRequest(Long roomId) {
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/com/aliens/backend/docs/ChatRestDocsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ void getChatSummary() throws Exception {
List<ChatRoom> chatRooms = new ArrayList<>();
ChatRoom chatRoom1 = mock(ChatRoom.class);
when(chatRoom1.getId()).thenReturn(1L);
when(chatRoom1.getStatus()).thenReturn(ChatRoomStatus.OPEN);
when(chatRoom1.getStatus()).thenReturn(ChatRoomStatus.OPENED);
ChatRoom chatRoom2 = mock(ChatRoom.class);
when(chatRoom2.getId()).thenReturn(2L);
when(chatRoom2.getStatus()).thenReturn(ChatRoomStatus.OPEN);
when(chatRoom2.getStatus()).thenReturn(ChatRoomStatus.OPENED);
chatRooms.add(chatRoom1);
chatRooms.add(chatRoom2);
Date now = new Date();
Expand Down

0 comments on commit 31888e4

Please sign in to comment.