Skip to content

Commit f0ee4f2

Browse files
committed
♻️ 동시성 적용 중간 커밋
1 parent 15bb20c commit f0ee4f2

File tree

3 files changed

+113
-107
lines changed

3 files changed

+113
-107
lines changed

backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java

Lines changed: 102 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import io.f1.backend.global.exception.errorcode.RoomErrorCode;
4646
import io.f1.backend.global.exception.errorcode.UserErrorCode;
4747

48+
import io.f1.backend.global.lock.DistributedLock;
4849
import lombok.RequiredArgsConstructor;
4950
import 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) {

backend/src/main/java/io/f1/backend/domain/game/websocket/controller/GameSocketController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public void initializeRoomSocket(@DestinationVariable Long roomId, Message<?> me
3939
public void reconnect(@DestinationVariable Long roomId, Message<?> message) {
4040

4141
UserPrincipal principal = getSessionUser(message);
42-
roomService.changeConnectedStatus(principal.getUserId(), ConnectionState.CONNECTED);
42+
roomService.changeConnectedStatus(principal.getUserId(),roomId, ConnectionState.CONNECTED);
4343
roomService.reconnectSendResponse(roomId, principal);
4444
}
4545

backend/src/main/java/io/f1/backend/domain/game/websocket/eventlistener/WebsocketEventListener.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.f1.backend.domain.game.websocket.DisconnectTaskManager;
88
import io.f1.backend.domain.user.dto.UserPrincipal;
99

10+
import io.f1.backend.global.lock.DistributedLock;
1011
import lombok.RequiredArgsConstructor;
1112
import lombok.extern.slf4j.Slf4j;
1213

@@ -36,7 +37,9 @@ public void handleDisconnectedListener(SessionDisconnectEvent event) {
3637
return;
3738
}
3839

39-
Long roomId = roomService.changeConnectedStatus(userId, ConnectionState.DISCONNECTED);
40+
Long roomId = roomService.getUserRoomId(userId);
41+
42+
changeConnectionStateWithLock(userId,roomId);
4043

4144
taskManager.scheduleDisconnectTask(
4245
userId,
@@ -47,4 +50,10 @@ public void handleDisconnectedListener(SessionDisconnectEvent event) {
4750
}
4851
});
4952
}
53+
54+
55+
@DistributedLock(prefix = "room", key = "#roomId")
56+
private void changeConnectionStateWithLock(Long userId, Long roomId){
57+
roomService.changeConnectedStatus(userId,roomId ,ConnectionState.DISCONNECTED);
58+
}
5059
}

0 commit comments

Comments
 (0)