-
Notifications
You must be signed in to change notification settings - Fork 3
[feat] 재연결 로직 구현 #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feat] 재연결 로직 구현 #102
Changes from 36 commits
d32fa2c
4a87b5b
2ebc45b
22e2dce
211a772
fb25877
7be49b7
51efbed
5ba8a13
07da462
6ce1897
527a6c5
bde0694
bdc1700
4abe282
849ef71
bc3fd2b
435d8f0
05b3c60
781c283
fd9baf5
fd9aff1
7bd4453
e3dcb00
15bfbab
700c734
4af5a2c
147ab05
31d1f76
1b54ded
357443d
6061c87
cb1f75d
3914981
e8616f4
f1dd3a2
ba3e466
a568032
e25f2f2
cce37c4
3aef18f
6a5ad37
c506712
5a1b865
6424848
0e644b7
b408205
cbb9a72
fc37e91
f9606ba
83544c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,17 @@ | ||
| package io.f1.backend.domain.game.model; | ||
|
|
||
| import io.f1.backend.domain.question.entity.Question; | ||
| import io.f1.backend.global.exception.CustomException; | ||
| import io.f1.backend.global.exception.errorcode.RoomErrorCode; | ||
|
|
||
| import lombok.Getter; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| import java.util.ArrayList; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.Executors; | ||
| import java.util.concurrent.ScheduledExecutorService; | ||
|
|
@@ -30,7 +34,7 @@ public class Room { | |
|
|
||
| private Map<String, Player> playerSessionMap = new ConcurrentHashMap<>(); | ||
|
|
||
| private Map<Long, String> userIdSessionMap = new ConcurrentHashMap<>(); | ||
| private final Set<Long> validatedUserIds = new HashSet<>(); | ||
|
|
||
| private final LocalDateTime createdAt = LocalDateTime.now(); | ||
|
|
||
|
|
@@ -47,6 +51,26 @@ public Room(Long id, RoomSetting roomSetting, GameSetting gameSetting, Player ho | |
| this.host = host; | ||
| } | ||
|
|
||
| public void addValidatedUserId(Long userId) { | ||
| validatedUserIds.add(userId); | ||
| } | ||
|
|
||
| public int getCurrentUserCnt() { | ||
| return validatedUserIds.size(); | ||
| } | ||
|
|
||
| public void addPlayer(String sessionId, Player player) { | ||
| Long userId = player.getId(); | ||
| if (!validatedUserIds.contains(userId)) { | ||
| throw new CustomException(RoomErrorCode.ROOM_ENTER_REQUIRED); | ||
| } | ||
|
|
||
| if (isHost(userId)) { | ||
| player.toggleReady(); | ||
| } | ||
| playerSessionMap.put(sessionId, player); | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 로직을 room 내부로 옮기니까 서비스 코드가 간결해지고, 가독성이 좋아진 것 같습니다 ! 👍 |
||
|
|
||
| public boolean isHost(Long id) { | ||
| return this.host.getId().equals(id); | ||
| } | ||
|
|
@@ -67,14 +91,14 @@ public void updateTimer(ScheduledFuture<?> timer) { | |
| this.timer = timer; | ||
| } | ||
|
|
||
| public void removeUserId(Long id) { | ||
| this.userIdSessionMap.remove(id); | ||
| } | ||
|
|
||
| public void removeSessionId(String sessionId) { | ||
| this.playerSessionMap.remove(sessionId); | ||
| } | ||
|
|
||
| public void removeUserId(Long userId) { | ||
| validatedUserIds.remove(userId); | ||
| } | ||
|
|
||
| public void increasePlayerCorrectCount(String sessionId) { | ||
| this.playerSessionMap.get(sessionId).increaseCorrectCount(); | ||
| } | ||
|
|
@@ -90,4 +114,18 @@ public Boolean isPlaying() { | |
| public void increaseCurrentRound() { | ||
| currentRound++; | ||
| } | ||
|
|
||
| public void reconnectSession(String oldSessionId, String newSessionId) { | ||
| Player player = playerSessionMap.get(oldSessionId); | ||
| removeSessionId(oldSessionId); | ||
| playerSessionMap.put(newSessionId, player); | ||
| } | ||
|
|
||
| public void updatePlayerConnectionState(String sessionId, ConnectionState newState) { | ||
| playerSessionMap.get(sessionId).updateState(newState); | ||
| } | ||
|
|
||
| public boolean isExit(String sessionId) { | ||
| return playerSessionMap.get(sessionId) == null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package io.f1.backend.domain.game.websocket.eventlistener; | ||
|
|
||
| import static io.f1.backend.domain.game.websocket.WebSocketUtils.getRoomSubscriptionDestination; | ||
| import static io.f1.backend.domain.game.websocket.WebSocketUtils.getSessionId; | ||
| import static io.f1.backend.domain.game.websocket.WebSocketUtils.getSessionUser; | ||
|
|
||
| import io.f1.backend.domain.game.websocket.service.SessionService; | ||
| import io.f1.backend.domain.user.dto.UserPrincipal; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| import org.springframework.context.event.EventListener; | ||
| import org.springframework.messaging.Message; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.web.socket.messaging.SessionConnectEvent; | ||
| import org.springframework.web.socket.messaging.SessionDisconnectEvent; | ||
| import org.springframework.web.socket.messaging.SessionSubscribeEvent; | ||
|
|
||
| @Slf4j | ||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class WebsocketEventListener { | ||
|
|
||
| private final SessionService sessionService; | ||
|
|
||
| @EventListener | ||
| public void handleConnectListener(SessionConnectEvent event) { | ||
| Message<?> message = event.getMessage(); | ||
|
|
||
| String sessionId = getSessionId(message); | ||
| UserPrincipal user = getSessionUser(message); | ||
|
|
||
| sessionService.addSession(sessionId, user.getUserId()); | ||
| } | ||
|
|
||
| @EventListener | ||
| public void handleSubscribeListener(SessionSubscribeEvent event) { | ||
|
|
||
| Message<?> message = event.getMessage(); | ||
|
|
||
| String sessionId = getSessionId(message); | ||
| UserPrincipal principal = getSessionUser(message); | ||
|
|
||
| String destination = getRoomSubscriptionDestination(message); | ||
|
|
||
| // todo 인덱스 길이 유효성 추가 | ||
| String[] subscribeType = destination.split("/"); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L4-변경제안]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분은 /user/queue/ 추가할때 같이 반영하도록하겠습니다. 감사합니다! |
||
|
|
||
| if (subscribeType[2].equals("room")) { | ||
| Long roomId = Long.parseLong(subscribeType[3]); | ||
| sessionService.addRoomId(roomId, sessionId); | ||
| sessionService.handleUserReconnect(roomId, sessionId, principal); | ||
| } | ||
| } | ||
|
|
||
| @EventListener | ||
| public void handleDisconnectedListener(SessionDisconnectEvent event) { | ||
|
|
||
| Message<?> message = event.getMessage(); | ||
|
|
||
| String sessionId = getSessionId(message); | ||
| UserPrincipal principal = getSessionUser(message); | ||
|
|
||
| sessionService.handleUserDisconnect(sessionId, principal); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API 명세서에 /auth/me response를 수정했습니다. 해당 PR이 merge가 되면 재연결 로직이 구현됨에 따라 명세서가 수정되었다고 말씀드리면 될 것 같습니다 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분은 재연결때문에 추가한건 아니였고, 추후에 1:1 응답에서 추가될 예정이라서 그부분 구현하고나서 제가 말씀드리겠습니다!
감사합니다.. 💪