Skip to content

Commit 873fbd2

Browse files
authored
Merge pull request #145 from boostcampwm-2022/133-socket-server-메모리-자료구조-redis로-포팅
[WIP] socket server redis room repository 구현체 구현
2 parents 435b741 + 8653992 commit 873fbd2

File tree

17 files changed

+331
-122
lines changed

17 files changed

+331
-122
lines changed

backend/rest/src/interview/entities/typeorm-interview-docs.entity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class TypeormInterviewDocsEntity
1818
@IsString()
1919
userId: string;
2020

21-
@Column({ length: 100 })
21+
@Column({ length: 200 })
2222
@IsString()
2323
videoUrl: string;
2424

backend/socket/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@nestjs/platform-express": "^9.0.0",
3131
"@nestjs/platform-socket.io": "^9.2.0",
3232
"@nestjs/websockets": "^9.2.0",
33+
"@socket.io/redis-adapter": "^8.0.0",
3334
"@types/aws-sdk": "^2.7.0",
3435
"aws-sdk": "^2.1267.0",
3536
"class-transformer": "^0.5.1",
@@ -38,10 +39,11 @@
3839
"fs": "^0.0.1-security",
3940
"joi": "^17.7.0",
4041
"lint-staged": "^13.0.4",
42+
"redis": "^4.5.1",
4143
"reflect-metadata": "^0.1.13",
4244
"rimraf": "^3.0.2",
4345
"rxjs": "^7.2.0",
44-
"socket.io": "^4.5.3",
46+
"socket.io": "^4.5.4",
4547
"uuid": "^9.0.0"
4648
},
4749
"devDependencies": {

backend/socket/src/app.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Module } from '@nestjs/common';
22
import { ConfigModule } from '@nestjs/config';
3-
import { envConfig } from './config/env.config';
3+
import { envConfig } from '@config';
44
import { RoomModule } from './room/room.module';
55

66
@Module({

backend/socket/src/config/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './env.config';
2+
export * from './redis.adapter';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { IoAdapter } from '@nestjs/platform-socket.io';
2+
import { ServerOptions } from 'socket.io';
3+
import { createAdapter } from '@socket.io/redis-adapter';
4+
import { createClient } from 'redis';
5+
6+
export const pubClient = createClient({ url: process.env.REDIS_URL });
7+
const subClient = pubClient.duplicate();
8+
9+
export class RedisIoAdapter extends IoAdapter {
10+
private adapterConstructor: ReturnType<typeof createAdapter>;
11+
12+
async connectToRedis(): Promise<void> {
13+
await Promise.all([pubClient.connect(), subClient.connect()]);
14+
this.adapterConstructor = createAdapter(pubClient, subClient);
15+
}
16+
17+
createIOServer(port: number, options?: ServerOptions): any {
18+
const server = super.createIOServer(port, options);
19+
server.adapter(this.adapterConstructor);
20+
return server;
21+
}
22+
}

backend/socket/src/constant/event.constant.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ export enum EVENT {
4242
}
4343

4444
export enum ERROR_MSG {
45-
FULL_ROOM = 'full_room',
46-
NO_ROOM = 'no_room',
47-
BUSY_ROOM = 'busy_room',
48-
NOT_ENOUGHT_USER = 'not_enough_user',
45+
FULL_ROOM = '방이 꽉 찼습니다.',
46+
NO_ROOM = '없는 방입니다.',
47+
BUSY_ROOM = '현재 면접이 진행중입니다.',
48+
NOT_ENOUGHT_USER = '인원이 부족합니다.',
4949
INVALID_REQUEST = 'invalid_request',
5050
BAD_REQUEST = 'invalid socket request',
5151
}

backend/socket/src/main.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
import { NestFactory } from '@nestjs/core';
22
import { AppModule } from './app.module';
3+
import { RedisIoAdapter } from '@config';
34

45
async function bootstrap() {
56
const app = await NestFactory.create(AppModule);
7+
8+
const redisIoAdapter = new RedisIoAdapter(app);
9+
await redisIoAdapter.connectToRedis();
10+
11+
app.useWebSocketAdapter(redisIoAdapter);
12+
613
await app.listen(8081);
714
}
15+
816
bootstrap();

backend/socket/src/room/repository/inmemory-room.repository.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
import { ROOM_PHASE } from '@constant';
2-
import { clientId, InmemoryRoom, roomUUID, User, userUUID } from '@types';
3-
import { RoomRepository } from './interface-room.repository';
2+
import { clientId, Room, roomUUID, User, userUUID } from '@types';
3+
import { RoomRepository } from './room.repository';
44

55
export class InmemoryRoomRepository implements RoomRepository {
6-
private rooms = new Map<roomUUID, InmemoryRoom>();
6+
private rooms = new Map<roomUUID, Room>();
77
private usersInRoom = new Map<roomUUID, Set<userUUID>>();
88
private clientUserIdMap = new Map<clientId, userUUID>();
99
private userClientIdMap = new Map<userUUID, clientId>();
1010
private userMap = new Map<userUUID, User>();
1111

12-
createRoom({ roomUUID, room }: { roomUUID: string; room: InmemoryRoom }) {
12+
async createRoom({ roomUUID, room }: { roomUUID: string; room: Room }) {
1313
this.rooms.set(roomUUID, room);
1414
this.usersInRoom.set(roomUUID, new Set());
1515
return room;
1616
}
1717

18-
deleteRoom(roomUUID: string) {
18+
async deleteRoom(roomUUID: string) {
1919
this.rooms.delete(roomUUID);
2020
this.usersInRoom.delete(roomUUID);
2121
}
2222

23-
getRoom(roomUUID: string) {
23+
async getRoom(roomUUID: string) {
2424
return this.rooms.get(roomUUID);
2525
}
2626

27-
getUsersInRoom(roomUUID: string) {
27+
async getUsersInRoom(roomUUID: string) {
2828
const userSet = this.usersInRoom.get(roomUUID);
2929
return [...userSet].map((uuid) => this.userMap.get(uuid));
3030
}
3131

32-
saveUserInRoom({
32+
async saveUserInRoom({
3333
clientId,
3434
roomUUID,
3535
user,
@@ -46,17 +46,17 @@ export class InmemoryRoomRepository implements RoomRepository {
4646
this.userClientIdMap.set(user.uuid, clientId);
4747
}
4848

49-
getUserByClientId(clientId: string) {
49+
async getUserByClientId(clientId: string) {
5050
const uuid = this.clientUserIdMap.get(clientId);
5151
return this.userMap.get(uuid);
5252
}
5353

54-
getClientIdByUser(uuid: string) {
54+
async getClientIdByUser(uuid: string) {
5555
const clientId = this.userClientIdMap.get(uuid);
5656
return clientId;
5757
}
5858

59-
removeUserInRoom({ roomUUID, user }: { roomUUID: string; user: User }) {
59+
async removeUserInRoom({ roomUUID, user }: { roomUUID: string; user: User }) {
6060
const userSet = this.usersInRoom.get(roomUUID);
6161
userSet.delete(user.uuid);
6262

@@ -67,17 +67,17 @@ export class InmemoryRoomRepository implements RoomRepository {
6767
this.clientUserIdMap.delete(clientId);
6868
}
6969

70-
getRoomPhase(roomUUID: string): ROOM_PHASE {
70+
async getRoomPhase(roomUUID: string) {
7171
const room = this.rooms.get(roomUUID);
7272
return room.phase;
7373
}
7474

75-
updateRoomPhase({ roomUUID, phase }: { roomUUID: string; phase: ROOM_PHASE }) {
75+
async updateRoomPhase({ roomUUID, phase }: { roomUUID: string; phase: ROOM_PHASE }) {
7676
const room = this.rooms.get(roomUUID);
7777
room.phase = phase;
7878
}
7979

80-
updateUserInfo({ uuid, updateUser }: { uuid: string; updateUser: Partial<User> }) {
80+
async updateUserInfo({ uuid, updateUser }: { uuid: string; updateUser: Partial<User> }) {
8181
const user = this.userMap.get(uuid);
8282
for (const key in updateUser) {
8383
user[key] = updateUser[key];
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { ROOM_PHASE } from '@constant';
2+
import { InmemoryRoom, User } from '@types';
3+
import { RoomRepository } from './room.repository';
4+
import { pubClient as R } from '@config';
5+
6+
export class RedisRoomRepository implements RoomRepository {
7+
// private rooms = new Map<roomUUID, InmemoryRoom>();
8+
// private usersInRoom = new Map<roomUUID, Set<userUUID>>();
9+
// private clientUserIdMap = new Map<clientId, userUUID>();
10+
// private userClientIdMap = new Map<userUUID, clientId>();
11+
// private userMap = new Map<userUUID, User>();
12+
13+
createRoom({ roomUUID, room }: { roomUUID: string; room: InmemoryRoom }): InmemoryRoom {
14+
throw new Error('Method not implemented.');
15+
}
16+
17+
deleteRoom(roomUUID: string): void {
18+
throw new Error('Method not implemented.');
19+
}
20+
21+
getRoom(roomUUID: string): InmemoryRoom {
22+
throw new Error('Method not implemented.');
23+
}
24+
25+
getUsersInRoom(roomUUID: string): User[] {
26+
throw new Error('Method not implemented.');
27+
}
28+
29+
saveUserInRoom({
30+
clientId,
31+
roomUUID,
32+
user,
33+
}: {
34+
clientId: string;
35+
roomUUID: string;
36+
user: User;
37+
}): void {
38+
throw new Error('Method not implemented.');
39+
}
40+
41+
getUserByClientId(clientId: string): User {
42+
throw new Error('Method not implemented.');
43+
}
44+
45+
getClientIdByUser(uuid: string): string {
46+
throw new Error('Method not implemented.');
47+
}
48+
49+
removeUserInRoom({ roomUUID, user }: { roomUUID: string; user: User }): void {
50+
throw new Error('Method not implemented.');
51+
}
52+
53+
getRoomPhase(roomUUID: string): ROOM_PHASE {
54+
throw new Error('Method not implemented.');
55+
}
56+
57+
updateRoomPhase({ roomUUID, phase }: { roomUUID: string; phase: ROOM_PHASE }): void {
58+
throw new Error('Method not implemented.');
59+
}
60+
61+
updateUserInfo({ uuid, updateUser }: { uuid: string; updateUser: Partial<User> }) {
62+
throw new Error('Method not implemented.');
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
1-
import { ROOM_PHASE, USER_ROLE } from '@constant';
2-
import { InmemoryRoom, User } from '@types';
1+
import { ROOM_PHASE } from '@constant';
2+
import { Room, User } from '@types';
33

44
export interface RoomRepository {
55
/**
66
* uuid를 key로 repository에 유저의 socket id를 저장할 객체를 생성하고
77
* uuid를 key로 방을 식별할 수 있는 객체에 room의 상태를 LOBBY로 저장하는 메서드입니다.
88
* @param uuid room을 식별할 수 있는 고유한 key
99
*/
10-
createRoom({ roomUUID, room }: { roomUUID: string; room: InmemoryRoom }): InmemoryRoom;
10+
createRoom({ roomUUID, room }: { roomUUID: string; room: Room }): Promise<Room>;
1111

12-
deleteRoom(roomUUID: string): void;
12+
deleteRoom(roomUUID: string): Promise<void>;
1313

1414
/**
1515
* uuid로 방 정보를 가져옵니다.
1616
* @param roomUUID
17-
* @Return InmemoryRoom
17+
* @Return Room
1818
*/
19-
getRoom(roomUUID: string): InmemoryRoom;
19+
getRoom(roomUUID: string): Promise<Room>;
2020

2121
/**
2222
* room uuid기반으로 해당 방에 존재하는 user 배열을 반환합니다.
2323
* @param roomUUID
2424
* @returns User[]
2525
*/
26-
getUsersInRoom(roomUUID: string): User[];
26+
getUsersInRoom(roomUUID: string): Promise<User[]>;
2727

2828
/**
2929
* room uuid 기반으로 해당 방에 user를 저장합니다.
@@ -38,37 +38,43 @@ export interface RoomRepository {
3838
clientId: string;
3939
roomUUID: string;
4040
user: User;
41-
}): void;
41+
}): Promise<void>;
4242

4343
/**
4444
* client socket id로 mapping된 user 객체를 반환합니다.
4545
* @param clientId
4646
* @returns User
4747
*/
48-
getUserByClientId(clientId: string): User;
48+
getUserByClientId(clientId: string): Promise<User>;
4949

50-
getClientIdByUser(uuid: string): string;
50+
getClientIdByUser(uuid: string): Promise<string>;
5151

5252
/**
5353
* roomUUID를 기반으로 해당 방에 있는 user를 제거합니다.
5454
* @param clientId socket id
5555
* @param user User
5656
*/
57-
removeUserInRoom({ roomUUID, user }: { roomUUID: string; user: User }): void;
57+
removeUserInRoom({ roomUUID, user }: { roomUUID: string; user: User }): Promise<void>;
5858

5959
/**
6060
* 방의 현재 phase를 반환합니다.
6161
* @param roomUUID
6262
* @returns ROOM_PHASE
6363
*/
64-
getRoomPhase(roomUUID: string): ROOM_PHASE;
64+
getRoomPhase(roomUUID: string): Promise<ROOM_PHASE>;
6565

6666
/**
6767
* 해당 room uuid의 room의 interview phase를 update 합니다.
6868
* @param roomUUID
6969
* @param phase
7070
*/
71-
updateRoomPhase({ roomUUID, phase }: { roomUUID: string; phase: ROOM_PHASE }): void;
71+
updateRoomPhase({ roomUUID, phase }: { roomUUID: string; phase: ROOM_PHASE }): Promise<void>;
7272

73-
updateUserInfo({ uuid, updateUser }: { uuid: string; updateUser: Partial<User> });
73+
updateUserInfo({
74+
uuid,
75+
updateUser,
76+
}: {
77+
uuid: string;
78+
updateUser: Partial<User>;
79+
}): Promise<void>;
7480
}

0 commit comments

Comments
 (0)