4545import io .f1 .backend .global .exception .errorcode .RoomErrorCode ;
4646import io .f1 .backend .global .exception .errorcode .UserErrorCode ;
4747
48+ import io .f1 .backend .global .lock .DistributedLock ;
4849import lombok .RequiredArgsConstructor ;
4950import lombok .extern .slf4j .Slf4j ;
5051
@@ -100,50 +101,50 @@ public RoomCreateResponse saveRoom(RoomCreateRequest request) {
100101 return new RoomCreateResponse (newId );
101102 }
102103
104+ @ DistributedLock (prefix = "room" , key = "#roomId" )
103105 public void enterRoom (RoomValidationRequest request ) {
104106
105107 Long roomId = request .roomId ();
106108
107- Object lock = roomLocks . computeIfAbsent (roomId , k -> new Object () );
109+ Room room = findRoom (roomId );
108110
109- synchronized (lock ) {
110- Room room = findRoom (request .roomId ());
111+ Long userId = getCurrentUserId ();
111112
112- Long userId = getCurrentUserId ();
113+ /* 다른 방 접속 시 기존 방은 exit 처리 - 탭 동시 로그인 시 (disconnected 리스너 작동x) */
114+ exitIfInAnotherRoom (room , userId );
113115
114- /* 다른 방 접속 시 기존 방은 exit 처리 - 탭 동시 로그인 시 (disconnected 리스너 작동x) */
115- exitIfInAnotherRoom (room , userId );
116+ /* reconnect */
117+ if (room .hasPlayer (userId )) {
118+ return ;
119+ }
116120
117- /* reconnect */
118- if (room .hasPlayer (userId )) {
119- return ;
120- }
121+ if (room .isPlaying ()) {
122+ throw new CustomException (RoomErrorCode .ROOM_GAME_IN_PROGRESS );
123+ }
121124
122- if (room .isPlaying ()) {
123- throw new CustomException (RoomErrorCode .ROOM_GAME_IN_PROGRESS );
124- }
125+ int maxUserCnt = room .getRoomSetting ().maxUserCount ();
126+ int currentCnt = room .getCurrentUserCnt ();
127+ if (maxUserCnt == currentCnt ) {
128+ throw new CustomException (RoomErrorCode .ROOM_USER_LIMIT_REACHED );
129+ }
125130
126- int maxUserCnt = room .getRoomSetting ().maxUserCount ();
127- int currentCnt = room .getCurrentUserCnt ();
128- if (maxUserCnt == currentCnt ) {
129- throw new CustomException (RoomErrorCode .ROOM_USER_LIMIT_REACHED );
130- }
131+ if (room .isPasswordIncorrect (request .password ())) {
132+ throw new CustomException (RoomErrorCode .WRONG_PASSWORD );
133+ }
131134
132- if (room .isPasswordIncorrect (request .password ())) {
133- throw new CustomException (RoomErrorCode .WRONG_PASSWORD );
134- }
135+ room .addPlayer (createPlayer ());
135136
136- room .addPlayer (createPlayer ());
137- }
138137 }
139138
140139 private void exitIfInAnotherRoom (Room room , Long userId ) {
141-
142140 Long joinedRoomId = userRoomRepository .getRoomId (userId );
143141
144142 if (joinedRoomId != null && !room .isSameRoom (joinedRoomId )) {
145- if (room .isPlaying ()) {
146- changeConnectedStatus (userId , ConnectionState .DISCONNECTED );
143+
144+ Room joinedRoom = findRoom (joinedRoomId );
145+
146+ if (joinedRoom .isPlaying ()) {
147+ changeConnectedStatus (userId , joinedRoomId , ConnectionState .DISCONNECTED );
147148 } else {
148149 exitRoom (joinedRoomId , getCurrentUserPrincipal ());
149150 }
@@ -161,7 +162,7 @@ public void initializeRoomSocket(Long roomId, UserPrincipal principal) {
161162
162163 /* 재연결 */
163164 if (room .isPlayerInState (userId , ConnectionState .DISCONNECTED )) {
164- changeConnectedStatus (userId , ConnectionState .CONNECTED );
165+ changeConnectedStatus (userId , roomId , ConnectionState .CONNECTED );
165166 cancelTask (userId );
166167 reconnectSendResponse (roomId , principal );
167168 return ;
@@ -175,71 +176,69 @@ public void initializeRoomSocket(Long roomId, UserPrincipal principal) {
175176 Quiz quiz = quizService .getQuizWithQuestionsById (quizId );
176177
177178 GameSettingResponse gameSettingResponse =
178- toGameSettingResponse (room .getGameSetting (), quiz );
179+ toGameSettingResponse (room .getGameSetting (), quiz );
179180
180181 PlayerListResponse playerListResponse = toPlayerListResponse (room );
181182
182183 SystemNoticeResponse systemNoticeResponse =
183- ofPlayerEvent (player .getNickname (), RoomEventType .ENTER );
184+ ofPlayerEvent (player .getNickname (), RoomEventType .ENTER );
184185
185186 String destination = getDestination (roomId );
186187
187188 userRoomRepository .addUser (player , room );
188189
189190 messageSender .sendPersonal (
190- getUserDestination (), MessageType .GAME_SETTING , gameSettingResponse , principal );
191+ getUserDestination (), MessageType .GAME_SETTING , gameSettingResponse , principal );
191192
192193 messageSender .sendBroadcast (destination , MessageType .ROOM_SETTING , roomSettingResponse );
193194 messageSender .sendBroadcast (destination , MessageType .PLAYER_LIST , playerListResponse );
194195 messageSender .sendBroadcast (destination , MessageType .SYSTEM_NOTICE , systemNoticeResponse );
195196 }
196197
198+ @ DistributedLock (prefix = "room" , key = "#roomId" )
197199 public void exitRoom (Long roomId , UserPrincipal principal ) {
198200
199- Object lock = roomLocks . computeIfAbsent (roomId , k -> new Object () );
201+ Room room = findRoom (roomId );
200202
201- synchronized (lock ) {
202- Room room = findRoom (roomId );
203+ if (!room .hasPlayer (principal .getUserId ())) {
204+ throw new CustomException (UserErrorCode .USER_NOT_FOUND );
205+ }
203206
204- if (!room .hasPlayer (principal .getUserId ())) {
205- throw new CustomException (UserErrorCode .USER_NOT_FOUND );
206- }
207+ Player removePlayer = createPlayer (principal );
207208
208- Player removePlayer = createPlayer ( principal );
209+ String destination = getDestination ( roomId );
209210
210- String destination = getDestination ( roomId );
211+ cleanRoom ( room , removePlayer );
211212
212- cleanRoom (room , removePlayer );
213+ messageSender .sendPersonal (
214+ getUserDestination (),
215+ MessageType .EXIT_SUCCESS ,
216+ new ExitSuccessResponse (true ),
217+ principal );
213218
214- messageSender .sendPersonal (
215- getUserDestination (),
216- MessageType .EXIT_SUCCESS ,
217- new ExitSuccessResponse (true ),
218- principal );
219+ SystemNoticeResponse systemNoticeResponse =
220+ ofPlayerEvent (removePlayer .nickname , RoomEventType .EXIT );
219221
220- SystemNoticeResponse systemNoticeResponse =
221- ofPlayerEvent (removePlayer .nickname , RoomEventType .EXIT );
222+ PlayerListResponse playerListResponse = toPlayerListResponse (room );
222223
223- PlayerListResponse playerListResponse = toPlayerListResponse (room );
224+ messageSender .sendBroadcast (destination , MessageType .PLAYER_LIST , playerListResponse );
225+ messageSender .sendBroadcast (
226+ destination , MessageType .SYSTEM_NOTICE , systemNoticeResponse );
224227
225- messageSender .sendBroadcast (destination , MessageType .PLAYER_LIST , playerListResponse );
226- messageSender .sendBroadcast (
227- destination , MessageType .SYSTEM_NOTICE , systemNoticeResponse );
228- }
229228 }
230229
231230 public RoomListResponse getAllRooms () {
232231 List <Room > rooms = roomRepository .findAll ();
233232 List <RoomResponse > roomResponses =
234- rooms .stream ()
235- .map (
236- room -> {
237- Long quizId = room .getGameSetting ().getQuizId ();
238- Quiz quiz = quizService .getQuizWithQuestionsById (quizId );
239-
240- return toRoomResponse (room , quiz );
241- })
242- .toList ();
233+ rooms .stream ()
234+ .map (
235+ room -> {
236+ Long quizId = room .getGameSetting ().getQuizId ();
237+ Quiz quiz = quizService .getQuizWithQuestionsById (quizId );
238+
239+ return toRoomResponse (room , quiz );
240+ })
241+ .toList ();
243242 return new RoomListResponse (roomResponses );
244243 }
245244
@@ -250,27 +249,27 @@ public void reconnectSendResponse(Long roomId, UserPrincipal principal) {
250249 String userDestination = getUserDestination ();
251250
252251 messageSender .sendBroadcast (
253- destination ,
254- MessageType .SYSTEM_NOTICE ,
255- ofPlayerEvent (principal .getUserNickname (), RoomEventType .RECONNECT ));
252+ destination ,
253+ MessageType .SYSTEM_NOTICE ,
254+ ofPlayerEvent (principal .getUserNickname (), RoomEventType .RECONNECT ));
256255
257256 if (room .isPlaying ()) {
258257 messageSender .sendPersonal (
259- userDestination ,
260- MessageType .SYSTEM_NOTICE ,
261- ofPlayerEvent (
262- principal .getUserNickname (), RoomEventType .RECONNECT_PRIVATE_NOTICE ),
263- principal );
258+ userDestination ,
259+ MessageType .SYSTEM_NOTICE ,
260+ ofPlayerEvent (
261+ principal .getUserNickname (), RoomEventType .RECONNECT_PRIVATE_NOTICE ),
262+ principal );
264263 messageSender .sendPersonal (
265- userDestination ,
266- MessageType .RANK_UPDATE ,
267- toRankUpdateResponse (room ),
268- principal );
264+ userDestination ,
265+ MessageType .RANK_UPDATE ,
266+ toRankUpdateResponse (room ),
267+ principal );
269268 messageSender .sendPersonal (
270- userDestination ,
271- MessageType .GAME_START ,
272- toGameStartResponse (room .getQuestions ()),
273- principal );
269+ userDestination ,
270+ MessageType .GAME_START ,
271+ toGameStartResponse (room .getQuestions ()),
272+ principal );
274273 } else {
275274 RoomSettingResponse roomSettingResponse = toRoomSettingResponse (room );
276275
@@ -279,26 +278,26 @@ public void reconnectSendResponse(Long roomId, UserPrincipal principal) {
279278 Quiz quiz = quizService .getQuizWithQuestionsById (quizId );
280279
281280 GameSettingResponse gameSettingResponse =
282- toGameSettingResponse (room .getGameSetting (), quiz );
281+ toGameSettingResponse (room .getGameSetting (), quiz );
283282
284283 PlayerListResponse playerListResponse = toPlayerListResponse (room );
285284
286285 messageSender .sendPersonal (
287- userDestination , MessageType .ROOM_SETTING , roomSettingResponse , principal );
286+ userDestination , MessageType .ROOM_SETTING , roomSettingResponse , principal );
288287 messageSender .sendPersonal (
289- userDestination , MessageType .PLAYER_LIST , playerListResponse , principal );
288+ userDestination , MessageType .PLAYER_LIST , playerListResponse , principal );
290289 messageSender .sendPersonal (
291- userDestination , MessageType .GAME_SETTING , gameSettingResponse , principal );
290+ userDestination , MessageType .GAME_SETTING , gameSettingResponse , principal );
292291 }
293292 }
294293
295- public Long changeConnectedStatus (Long userId , ConnectionState newState ) {
296- Long roomId = userRoomRepository .getRoomId (userId );
294+ public void changeConnectedStatus (Long userId , Long roomId , ConnectionState newState ) {
297295 Room room = findRoom (roomId );
298-
299296 room .updatePlayerConnectionState (userId , newState );
297+ }
300298
301- return roomId ;
299+ public Long getUserRoomId (Long userId ) {
300+ return userRoomRepository .getRoomId (userId );
302301 }
303302
304303 public void cancelTask (Long userId ) {
@@ -324,8 +323,8 @@ private Player createPlayer() {
324323
325324 public Room findRoom (Long roomId ) {
326325 return roomRepository
327- .findRoom (roomId )
328- .orElseThrow (() -> new CustomException (RoomErrorCode .ROOM_NOT_FOUND ));
326+ .findRoom (roomId )
327+ .orElseThrow (() -> new CustomException (RoomErrorCode .ROOM_NOT_FOUND ));
329328 }
330329
331330 private void removeRoom (Room room ) {
@@ -339,40 +338,38 @@ private void changeHost(Room room, Player host) {
339338 Map <Long , Player > playerMap = room .getPlayerMap ();
340339
341340 Optional <Player > nextHost =
342- playerMap .entrySet ().stream ()
343- .filter (entry -> !entry .getKey ().equals (host .getId ()))
344- .filter (entry -> entry .getValue ().getState () == ConnectionState .CONNECTED )
345- .map (Map .Entry ::getValue )
346- .findFirst ();
341+ playerMap .entrySet ().stream ()
342+ .filter (entry -> !entry .getKey ().equals (host .getId ()))
343+ .filter (entry -> entry .getValue ().getState () == ConnectionState .CONNECTED )
344+ .map (Map .Entry ::getValue )
345+ .findFirst ();
347346
348347 room .updateHost (
349- nextHost .orElseThrow (() -> new CustomException (RoomErrorCode .PLAYER_NOT_FOUND )));
348+ nextHost .orElseThrow (() -> new CustomException (RoomErrorCode .PLAYER_NOT_FOUND )));
350349 }
351350
352351 private String getUserDestination () {
353352 return "/queue" ;
354353 }
355354
355+ @ DistributedLock (prefix = "room" , key = "#roomId" )
356356 public void exitRoomForDisconnectedPlayer (Long roomId , Player player ) {
357357
358- Object lock = roomLocks .computeIfAbsent (roomId , k -> new Object ());
358+ // 연결 끊긴 플레이어 exit 로직 타게 해주기
359+ Room room = findRoom (roomId );
359360
360- synchronized (lock ) {
361- // 연결 끊긴 플레이어 exit 로직 타게 해주기
362- Room room = findRoom (roomId );
361+ cleanRoom (room , player );
363362
364- cleanRoom ( room , player );
363+ String destination = getDestination ( roomId );
365364
366- String destination = getDestination (roomId );
365+ SystemNoticeResponse systemNoticeResponse =
366+ ofPlayerEvent (player .nickname , RoomEventType .EXIT );
367367
368- SystemNoticeResponse systemNoticeResponse =
369- ofPlayerEvent (player .nickname , RoomEventType .EXIT );
368+ messageSender .sendBroadcast (
369+ destination , MessageType .SYSTEM_NOTICE , systemNoticeResponse );
370+ messageSender .sendBroadcast (
371+ destination , MessageType .PLAYER_LIST , toPlayerListResponse (room ));
370372
371- messageSender .sendBroadcast (
372- destination , MessageType .SYSTEM_NOTICE , systemNoticeResponse );
373- messageSender .sendBroadcast (
374- destination , MessageType .PLAYER_LIST , toPlayerListResponse (room ));
375- }
376373 }
377374
378375 private void cleanRoom (Room room , Player player ) {
0 commit comments