diff --git a/src/main/java/site/youtogether/message/ChatHistory.java b/src/main/java/site/youtogether/message/ChatHistory.java index 44fd415..5bc6e99 100644 --- a/src/main/java/site/youtogether/message/ChatHistory.java +++ b/src/main/java/site/youtogether/message/ChatHistory.java @@ -11,12 +11,14 @@ public class ChatHistory { private MessageType messageType; + private Long chatId; private Long userId; private String content; private String createdAt; public ChatHistory(ChatMessage chatMessage) { this.messageType = chatMessage.getMessageType(); + this.chatId = chatMessage.getChatId(); this.userId = chatMessage.getUserId(); this.content = chatMessage.getContent(); this.createdAt = chatMessage.getCreatedAt(); @@ -24,6 +26,7 @@ public ChatHistory(ChatMessage chatMessage) { public ChatHistory(AlarmMessage alarmMessage) { this.messageType = alarmMessage.getMessageType(); + this.chatId = alarmMessage.getChatId(); this.userId = null; this.content = alarmMessage.getContent(); this.createdAt = alarmMessage.getCreatedAt(); diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index fe51b08..16a558a 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -6,14 +6,13 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import site.youtogether.exception.room.RoomNoExistenceException; import site.youtogether.exception.user.UserNoExistenceException; import site.youtogether.message.AlarmMessage; -import site.youtogether.message.ChatHistory; import site.youtogether.message.application.MessageService; import site.youtogether.playlist.Playlist; import site.youtogether.playlist.infrastructure.PlaylistStorage; @@ -37,7 +36,7 @@ public class RoomService { private final PlaylistStorage playlistStorage; private final UserStorage userStorage; private final MessageService messageService; - private final RedisTemplate chatRedisTemplate; + private final StringRedisTemplate redisTemplate; public NewRoom create(Long userId, RoomSettings roomSettings, LocalDateTime now) { String roomCode = RandomUtil.generateRandomCode(ROOM_CODE_LENGTH); diff --git a/src/main/java/site/youtogether/user/User.java b/src/main/java/site/youtogether/user/User.java index b4101be..bcd0d91 100644 --- a/src/main/java/site/youtogether/user/User.java +++ b/src/main/java/site/youtogether/user/User.java @@ -1,8 +1,12 @@ package site.youtogether.user; +import static site.youtogether.util.AppConstants.*; + +import java.util.ArrayDeque; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.Queue; import org.springframework.data.annotation.Id; @@ -36,6 +40,7 @@ public class User { private String nickname; private Map history = new HashMap<>(); + private Queue roomCodeQueue = new ArrayDeque<>(); @Builder private User(Long id, String nickname, String currentRoomCode, boolean activate) { @@ -103,7 +108,13 @@ public void changeOtherUserRole(User targetUser, Role newUserRole) { public void enterRoom(String roomCode) { if (isFirstTimeEntering(roomCode)) { history.put(roomCode, Role.GUEST); + if (roomCodeQueue.size() >= USER_HISTORY_LENGTH) { + removeOldestRoomCode(); + } + } else { + roomCodeQueue.remove(roomCode); } + roomCodeQueue.offer(roomCode); currentRoomCode = roomCode; activate = true; } @@ -133,6 +144,11 @@ private boolean isFirstTimeEntering(String roomCode) { return !history.containsKey(roomCode); } + private void removeOldestRoomCode() { + String deletedRoomCode = roomCodeQueue.poll(); + history.remove(deletedRoomCode); + } + private boolean isInSameRoom(User user, User targetUser) { return user.getCurrentRoomCode().equals(targetUser.getCurrentRoomCode()); } diff --git a/src/main/java/site/youtogether/util/AppConstants.java b/src/main/java/site/youtogether/util/AppConstants.java index fefb2c3..fcf6134 100644 --- a/src/main/java/site/youtogether/util/AppConstants.java +++ b/src/main/java/site/youtogether/util/AppConstants.java @@ -7,6 +7,7 @@ public final class AppConstants { public static final int ROOM_CODE_LENGTH = 10; + public static final int USER_HISTORY_LENGTH = 10; public static final String STOMP_ENDPOINT = "/stomp"; public static final String USER_ID = "userId"; public static final String ROOM_CODE = "roomCode"; diff --git a/src/test/java/site/youtogether/room/application/RoomServiceTest.java b/src/test/java/site/youtogether/room/application/RoomServiceTest.java index f46b126..3f52553 100644 --- a/src/test/java/site/youtogether/room/application/RoomServiceTest.java +++ b/src/test/java/site/youtogether/room/application/RoomServiceTest.java @@ -253,6 +253,50 @@ void changeRoom() throws Exception { assertThat(savedRoom.getTitle()).isEqualTo(updateTitle); } + @Test + @DisplayName("유저가 입장한 방 기록은 최대 10개만 방문 순서대로 유지된다") + void userHistory() throws Exception { + // given + User user = createUser(1L); + + // when + for (int i = 0; i < 100; i++) { + Room room = createRoom(LocalDateTime.now(), "roomCode" + i); + roomService.enter(room.getCode(), user.getId(), null); + } + + // then + User savedUser = userStorage.findById(user.getId()).get(); + assertThat(savedUser.getHistory().size()).isEqualTo(10); + } + + @Test + @DisplayName("방을 재입장하는 경우, 방 기록 순서는 갱신된다") + void userHistoryUpdate() throws Exception { + // given + User user = createUser(1L); + + Room firstRoom = createRoom(LocalDateTime.now(), "firstRoomCode"); + roomService.enter(firstRoom.getCode(), user.getId(), null); + + Room room1 = createRoom(LocalDateTime.now(), "room1"); + roomService.enter(room1.getCode(), user.getId(), null); + + Room room2 = createRoom(LocalDateTime.now(), "room2"); + roomService.enter(room2.getCode(), user.getId(), null); + + Room room3 = createRoom(LocalDateTime.now(), "room3"); + roomService.enter(room3.getCode(), user.getId(), null); + + // when + roomService.enter(firstRoom.getCode(), user.getId(), null); + + // then + User savedUser = userStorage.findById(user.getId()).get(); + assertThat(savedUser.getHistory().size()).isEqualTo(4); + assertThat(savedUser.getRoomCodeQueue()).containsExactly(room1.getCode(), room2.getCode(), room3.getCode(), firstRoom.getCode()); + } + private User createUser(Long userId) { User user = User.builder() .id(userId) diff --git a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java index 5ff6804..3173b7c 100644 --- a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java +++ b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java @@ -779,10 +779,10 @@ private List generateRooms(int count) { private List createChatHistory(String roomCode) { return List.of( - new ChatHistory(MessageType.CHAT, 1L, "안녕하세요", LocalDateTime.now().toString()), - new ChatHistory(MessageType.ALARM, null, "yeon님이 입장하셨습니다.", LocalDateTime.now().toString()), - new ChatHistory(MessageType.CHAT, 2L, "방가방가 햄토리", LocalDateTime.now().toString()), - new ChatHistory(MessageType.CHAT, 1L, "ㄷㄷ", LocalDateTime.now().toString()) + new ChatHistory(MessageType.CHAT, 123L, 1L, "안녕하세요", LocalDateTime.now().toString()), + new ChatHistory(MessageType.ALARM, 124L, null, "yeon님이 입장하셨습니다.", LocalDateTime.now().toString()), + new ChatHistory(MessageType.CHAT, 125L, 2L, "방가방가 햄토리", LocalDateTime.now().toString()), + new ChatHistory(MessageType.CHAT, 126L, 1L, "ㄷㄷ", LocalDateTime.now().toString()) ); } diff --git a/src/test/java/site/youtogether/user/UserTest.java b/src/test/java/site/youtogether/user/UserTest.java index f405e2d..08f280c 100644 --- a/src/test/java/site/youtogether/user/UserTest.java +++ b/src/test/java/site/youtogether/user/UserTest.java @@ -167,4 +167,67 @@ void changeNicknameNoEnterRoom() throws Exception { assertThat(user.getNickname()).isEqualTo(updateNickname); } + @Test + @DisplayName("방 참여 기록은 최대 10개까지 저장된다") + void historyLength() throws Exception { + // given + User user = User.builder() + .id(1L) + .nickname("황똥땡") + .build(); + + // when + for (int i = 0; i < 10; i++) { + user.enterRoom("roomCode" + i); + } + + // then + assertThat(user.getHistory().size()).isEqualTo(10); + } + + @Test + @DisplayName("방 참여 기록이 10개를 넘어가면, 가장 오래전에 방문한 방의 기록부터 제거한다") + void historyLimitExceed() throws Exception { + // given + User user = User.builder() + .id(1L) + .nickname("황똥땡") + .build(); + + String firstRoomCode = "firstRoomCode"; + user.enterRoom(firstRoomCode); + + // when + for (int i = 0; i < 10; i++) { + user.enterRoom("roomCode" + i); + } + + // then + assertThat(user.getHistory().size()).isEqualTo(10); + assertThat(user.getHistory()).doesNotContainKey(firstRoomCode); + } + + @Test + @DisplayName("방을 재입장 한 경우, 방문 순서가 갱신된다") + void historyUpdate() throws Exception { + // given + User user = User.builder() + .id(1L) + .nickname("황똥땡") + .build(); + + String firstRoomCode = "firstRoomCode"; + user.enterRoom(firstRoomCode); + + // when + for (int i = 0; i < 3; i++) { + user.enterRoom("roomCode" + i); + } + user.enterRoom(firstRoomCode); + + // then + assertThat(user.getHistory().size()).isEqualTo(4); + assertThat(user.getRoomCodeQueue()).containsExactly("roomCode0", "roomCode1", "roomCode2", "firstRoomCode"); + } + }