From afc2ee5c06c31fcfb52204ba4aac68c0ee6f8e75 Mon Sep 17 00:00:00 2001 From: zerozae <84398970+park0jae@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:41:58 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=EC=9E=90=20=ED=98=84=ED=99=A9=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 인게임 입장 시 세션 ID 업데이트 로직 추가 * feat: 실시간 접속자 현황 파악 기능 구현 --------- Co-authored-by: marooo326 --- .../api/domain/game/service/GameService.java | 9 +++- .../api/domain/online/OnlineController.java | 27 +++++++++++ .../pgms/api/domain/online/OnlineService.java | 46 +++++++++++++++++++ .../online/dto/OnlineMemberGetResponse.java | 27 +++++++++++ .../controller/GameSocketController.java | 10 ++-- .../com/pgms/coreinfraredis/entity/Guest.java | 2 +- .../coreinfraredis/entity/OnlineMember.java | 17 +++++++ .../repository/OnlineMemberRepository.java | 8 ++++ 8 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 api/src/main/java/com/pgms/api/domain/online/OnlineController.java create mode 100644 api/src/main/java/com/pgms/api/domain/online/OnlineService.java create mode 100644 api/src/main/java/com/pgms/api/domain/online/dto/OnlineMemberGetResponse.java create mode 100644 core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/OnlineMember.java create mode 100644 core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/repository/OnlineMemberRepository.java diff --git a/api/src/main/java/com/pgms/api/domain/game/service/GameService.java b/api/src/main/java/com/pgms/api/domain/game/service/GameService.java index 1cebaaf..5eb4b81 100644 --- a/api/src/main/java/com/pgms/api/domain/game/service/GameService.java +++ b/api/src/main/java/com/pgms/api/domain/game/service/GameService.java @@ -11,6 +11,7 @@ import com.pgms.api.domain.game.dto.response.GameQuestionGetResponse; import com.pgms.api.domain.game.dto.response.GameRoomMemberGetResponse; +import com.pgms.api.global.exception.GameException; import com.pgms.api.global.exception.SocketException; import com.pgms.api.socket.dto.request.GameFinishRequest; import com.pgms.api.socket.dto.request.GameInfoUpdateRequest; @@ -55,12 +56,16 @@ public class GameService { private final Producer producer; // ============================== 입장 확인 및 첫 라운드 스타트 ============================== - public void startFirstRound(Long roomId) { + public void startFirstRound(Long roomId, Long accountId, String sessionId) { final GameInfo gameInfo = getGameInfo(roomId); final GameRoom gameRoom = getGameRoom(roomId); - // 카운트만 올려줌 + final GameRoomMember gameRoomMember = gameRoomMemberRepository.findByMemberId(accountId) + .orElseThrow(() -> new GameException(GameRoomErrorCode.GAME_ROOM_MEMBER_NOT_FOUND)); + + // 카운트만 올려줌. TODO : 나중에 한명이 여러번 입장처리 못하게 수정 gameInfo.enter(); + gameRoomMember.updateSessionId(sessionId); // 모든 멤버가 입장했을 때 if (gameInfo.isAllEntered(gameRoom.getCurrentPlayer())) { diff --git a/api/src/main/java/com/pgms/api/domain/online/OnlineController.java b/api/src/main/java/com/pgms/api/domain/online/OnlineController.java new file mode 100644 index 0000000..d8541f6 --- /dev/null +++ b/api/src/main/java/com/pgms/api/domain/online/OnlineController.java @@ -0,0 +1,27 @@ +package com.pgms.api.domain.online; + +import java.util.Set; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.pgms.api.domain.online.dto.OnlineMemberGetResponse; +import com.pgms.coredomain.response.ApiResponse; +import com.pgms.coresecurity.resolver.Account; +import com.pgms.coresecurity.resolver.CurrentAccount; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class OnlineController { + + private final OnlineService onlineService; + + @GetMapping("/api/v1/online") + public ResponseEntity>> getOnlineMembers( + @CurrentAccount Account account) { + return ResponseEntity.ok(ApiResponse.of(onlineService.getOnlineMembers(account))); + } +} diff --git a/api/src/main/java/com/pgms/api/domain/online/OnlineService.java b/api/src/main/java/com/pgms/api/domain/online/OnlineService.java new file mode 100644 index 0000000..a276137 --- /dev/null +++ b/api/src/main/java/com/pgms/api/domain/online/OnlineService.java @@ -0,0 +1,46 @@ +package com.pgms.api.domain.online; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.pgms.api.domain.online.dto.OnlineMemberGetResponse; +import com.pgms.coredomain.repository.GameRoomMemberRepository; +import com.pgms.coreinfraredis.entity.OnlineMember; +import com.pgms.coreinfraredis.repository.OnlineMemberRepository; +import com.pgms.coresecurity.resolver.Account; + +import lombok.RequiredArgsConstructor; + +@Service +@Transactional +@RequiredArgsConstructor +public class OnlineService { + + private final GameRoomMemberRepository gameRoomMemberRepository; + private final OnlineMemberRepository onlineMemberRepository; + + public Set getOnlineMembers(Account account) { + HashSet onlineMembers = new HashSet<>(); + + OnlineMember currentMember = new OnlineMember(account.id(), account.nickname()); + onlineMemberRepository.save(currentMember); + + gameRoomMemberRepository.findAll() + .forEach(gameRoomMember -> onlineMembers.add(new OnlineMemberGetResponse( + gameRoomMember.getMemberId(), + gameRoomMember.getNickname()))); + + Iterable onlineMembersIterable = onlineMemberRepository.findAll(); + onlineMembersIterable.forEach(onlineMember -> { + if (onlineMember != null) { + onlineMembers.add(new OnlineMemberGetResponse( + onlineMember.getId(), + onlineMember.getNickname())); + } + }); + return onlineMembers; + } +} diff --git a/api/src/main/java/com/pgms/api/domain/online/dto/OnlineMemberGetResponse.java b/api/src/main/java/com/pgms/api/domain/online/dto/OnlineMemberGetResponse.java new file mode 100644 index 0000000..ed682ae --- /dev/null +++ b/api/src/main/java/com/pgms/api/domain/online/dto/OnlineMemberGetResponse.java @@ -0,0 +1,27 @@ +package com.pgms.api.domain.online.dto; + +import java.util.Objects; + +public record OnlineMemberGetResponse( + Long memberId, + String nickname +) { + public static OnlineMemberGetResponse of(Long memberId, String nickname) { + return new OnlineMemberGetResponse(memberId, nickname); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + OnlineMemberGetResponse that = (OnlineMemberGetResponse)o; + return Objects.equals(memberId, that.memberId) && Objects.equals(nickname, that.nickname); + } + + @Override + public int hashCode() { + return Objects.hash(memberId, nickname); + } +} diff --git a/api/src/main/java/com/pgms/api/socket/controller/GameSocketController.java b/api/src/main/java/com/pgms/api/socket/controller/GameSocketController.java index e0d5b41..eef1dc8 100644 --- a/api/src/main/java/com/pgms/api/socket/controller/GameSocketController.java +++ b/api/src/main/java/com/pgms/api/socket/controller/GameSocketController.java @@ -4,6 +4,7 @@ import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.web.bind.annotation.RestController; import com.pgms.api.domain.game.service.GameService; @@ -25,9 +26,12 @@ public class GameSocketController { @MessageMapping("/game/{roomId}/connect") public void roundStart( @Header("AccountId") Long accountId, - @DestinationVariable Long roomId) { - log.info(">>>>>> Member Connected in game : roomId = {}, accountId = {}", roomId, accountId); - gameService.startFirstRound(roomId); + @DestinationVariable Long roomId, + SimpMessageHeaderAccessor headerAccessor) { + final String sessionId = headerAccessor.getSessionId(); + log.info(">>>>>> Member Connected in game : roomId = {}, accountId = {}, sessionId = {}", + roomId, accountId, sessionId); + gameService.startFirstRound(roomId, accountId, sessionId); } // 게임 중 실시간 정보 업데이트 - 문장, 코드 diff --git a/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/Guest.java b/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/Guest.java index 3f29179..1ba431e 100644 --- a/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/Guest.java +++ b/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/Guest.java @@ -10,7 +10,7 @@ @Getter @AllArgsConstructor -@RedisHash(value = "guest", timeToLive = 36000L) +@RedisHash(value = "guest", timeToLive = 1800L) public class Guest implements Serializable { @Id private Long id; diff --git a/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/OnlineMember.java b/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/OnlineMember.java new file mode 100644 index 0000000..5b3d7e1 --- /dev/null +++ b/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/entity/OnlineMember.java @@ -0,0 +1,17 @@ +package com.pgms.coreinfraredis.entity; + +import org.springframework.data.redis.core.RedisHash; + +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@RedisHash(value = "onlineMember", timeToLive = 20L) +public class OnlineMember { + @Id + private Long id; + + private String nickname; +} diff --git a/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/repository/OnlineMemberRepository.java b/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/repository/OnlineMemberRepository.java new file mode 100644 index 0000000..12a1e5d --- /dev/null +++ b/core/core-infra-redis/src/main/java/com/pgms/coreinfraredis/repository/OnlineMemberRepository.java @@ -0,0 +1,8 @@ +package com.pgms.coreinfraredis.repository; + +import org.springframework.data.repository.CrudRepository; + +import com.pgms.coreinfraredis.entity.OnlineMember; + +public interface OnlineMemberRepository extends CrudRepository { +}