* 로직 이해하기
- createRoom 할때 일어나는 일
- joinRoom시 일어나는 일
- start Game 누르면 나머지 event들이 알아서 발생되는군
- start Game 누르면 생기는일
- 퀴즈, 정답을 레디스에 올리는구나
* gameService 주석
@Injectable()
export class GameService {
/**
* 게임 서비스에서 사용되는 Redis 명령어 설명
*
* Redis 키 구조:
* - Room:{gameId} : 게임 방 정보를 저장하는 해시
* - Player:{clientId} : 플레이어 정보를 저장하는 해시
* - Room:{gameId}:Players : 게임 방의 플레이어 목록을 저장하는 Set
* - Room:{gameId}:Leaderboard : 게임 방의 리더보드를 저장하는 Sorted Set
* - Room:{gameId}:Quiz:Set : 게임 방의 퀴즈 ID 목록을 저장하는 Set
*/
async startGame(startGameDto: StartGameDto, clientId: string): Promise<void> {
const { gameId } = startGameDto;
const roomKey = REDIS_KEY.ROOM(gameId);
/**
* Redis HGETALL 명령어
* @description 해시에 저장된 모든 필드와 값을 가져옴
* @example
* HGETALL Room:123
* 결과: { host: "client1", status: "waiting", title: "Game1", ... }
*/
const room = await this.redis.hgetall(roomKey);
// 기존 퀴즈 데이터 초기화
const prevQuizList = await this.redis.smembers(REDIS_KEY.ROOM_QUIZ_SET(gameId));
for (const prevQuiz of prevQuizList) {
/**
* Redis DEL 명령어
* @description 지정된 키를 삭제
* @example DEL Room:123:Quiz:1
*/
await this.redis.del(REDIS_KEY.ROOM_QUIZ(gameId, prevQuiz));
await this.redis.del(REDIS_KEY.ROOM_QUIZ_CHOICES(gameId, prevQuiz));
}
/**
* Redis SADD 명령어
* @description Set에 하나 이상의 멤버를 추가
* @example
* SADD Room:123:Quiz:Set quiz1 quiz2 quiz3
* 결과: 추가된 멤버 수
*/
await this.redis.sadd(
REDIS_KEY.ROOM_QUIZ_SET(gameId),
...selectedQuizList.map((quiz) => quiz.id)
);
/**
* Redis HMSET 명령어
* @description 해시에 여러 필드-값 쌍을 설정
* @example
* HMSET Room:123:Quiz:1 quiz "Question?" answer "2" limitTime "30"
*/
await this.redis.hmset(REDIS_KEY.ROOM_QUIZ(gameId, quiz.id), {
quiz: quiz.quiz,
answer: quiz.choiceList.find((choice) => choice.isAnswer).order,
limitTime: quiz.limitTime.toString(),
choiceCount: quiz.choiceList.length.toString()
});
// 리더보드 초기화
/**
* Redis ZRANGE 명령어
* @description Sorted Set의 범위 내 멤버를 가져옴
* @example
* ZRANGE Room:123:Leaderboard 0 -1
* 결과: ["player1", "player2", ...]
*/
const leaderboard = await this.redis.zrange(REDIS_KEY.ROOM_LEADERBOARD(gameId), 0, -1);
/**
* Redis ZADD 명령어
* @description Sorted Set에 점수와 함께 멤버를 추가
* @example
* ZADD Room:123:Leaderboard 0 player1
*/
for (const playerId of leaderboard) {
await this.redis.zadd(REDIS_KEY.ROOM_LEADERBOARD(gameId), 0, playerId);
}
}
async disconnect(clientId: string): Promise<void> {
const playerKey = REDIS_KEY.PLAYER(clientId);
const playerData = await this.redis.hgetall(playerKey);
/**
* Redis SREM 명령어
* @description Set에서 지정된 멤버를 제거
* @example
* SREM Room:123:Players player1
*/
await this.redis.srem(REDIS_KEY.ROOM_PLAYERS(playerData.gameId), clientId);
/**
* Redis ZREM 명령어
* @description Sorted Set에서 지정된 멤버를 제거
* @example
* ZREM Room:123:Leaderboard player1
*/
await this.redis.zrem(REDIS_KEY.ROOM_LEADERBOARD(playerData.gameId), clientId);
/**
* Redis SRANDMEMBER 명령어
* @description Set에서 무작위 멤버를 가져옴
* @example
* SRANDMEMBER Room:123:Players
* 결과: "player2"
*/
const newHost = await this.redis.srandmember(REDIS_KEY.ROOM_PLAYERS(playerData.gameId));
/**
* Redis SET 명령어
* @description 키에 문자열 값을 설정
* @example
* SET Player:123:Changes Disconnect
*/
await this.redis.set(`${playerKey}:Changes`, 'Disconnect');
}
/**
* Redis Pub/Sub 이벤트 구독 설정
* @description 게임 진행에 필요한 여러 Redis 이벤트를 구독
*/
async subscribeRedisEvent(server: Server): Promise<void> {
/**
* Redis CONFIG SET 명령어
* @description Redis 설정을 변경
* @example
* CONFIG SET notify-keyspace-events KEhx
* K: 키스페이스 이벤트
* E: 키이벤트
* h: 해시 이벤트
* x: 만료 이벤트
*/
this.redis.config('SET', 'notify-keyspace-events', 'KEhx');
/**
* Redis PSUBSCRIBE 명령어
* @description 패턴에 매칭되는 채널을 구독
* @example
* PSUBSCRIBE __keyspace@0__:Room:*
*/
const subscriber = this.redis.duplicate();
await subscriber.psubscribe('scoring:*');
subscriber.on('pmessage', async (_pattern, channel, message) => {
// 이벤트 처리 로직...
});
}
}
'개발일지' 카테고리의 다른 글
24. 11. 19. 개발일지 // test-code 의존성 수정, redis 구독 리팩토링, 진행중게임에 들어올수없음 (0) | 2024.11.20 |
---|---|
24. 11. 18. 개발일지 // api vs 서비스주입, redis 캐시 (1) | 2024.11.19 |
24.11.14. 발표자료 // n+1문제해결, 변경감지, redis 설계 (0) | 2024.11.14 |
24.11.14. 개발일지 // 자동배포, 깃헙액션에서 db test, ssh 터널링 db 연결 (1) | 2024.11.14 |
[week2-수요일] 개발일지 // 테이블설계 (0) | 2024.08.28 |