|
1 |
| -import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; |
2 |
| -import { Cluster, Redis } from 'ioredis'; |
3 |
| -import { createAdapter } from '@socket.io/redis-adapter'; |
4 |
| -import { User } from './user.interface'; |
5 |
| -import { getRandomAdjective, getRandomBrightColor, getRandomNoun } from '../utils/random'; |
| 1 | +import { Injectable, OnModuleInit } from '@nestjs/common'; |
| 2 | +import { Cluster } from 'ioredis'; |
6 | 3 | import { RoomRepository } from './room.repository';
|
7 | 4 | import { QuestionDto } from '../event/dto/Question.dto';
|
8 | 5 |
|
9 |
| -import dotenv from 'dotenv'; |
10 |
| -import path from 'path'; |
11 |
| -import { fileURLToPath } from 'url'; |
12 |
| -import { dirname } from 'path'; |
13 | 6 | import { ChatException, CHATTING_SOCKET_ERROR } from '../chat/chat.error';
|
14 | 7 | import { Socket } from 'socket.io';
|
15 |
| - |
16 |
| -// 현재 파일의 URL을 파일 경로로 변환 |
17 |
| -const __filename = fileURLToPath(import.meta.url); |
18 |
| -const __dirname = dirname(__filename); |
19 |
| - |
20 |
| -// 상위 디렉터리의 .env 파일을 불러오기 |
21 |
| -dotenv.config({ path: path.resolve(__dirname, '../../.env') }); |
22 |
| -const REDIS_CONFIG = JSON.parse(process.env.REDIS_CONFIG!); |
23 |
| - |
24 |
| -function createRandomNickname(){ |
25 |
| - return `${getRandomAdjective()} ${getRandomNoun()}`; |
26 |
| -} |
27 |
| - |
28 |
| -function createRandomUserInstance(address: string, userAgent: string): User { |
29 |
| - return { |
30 |
| - address, |
31 |
| - userAgent, |
32 |
| - nickname: createRandomNickname(), |
33 |
| - color: getRandomBrightColor(), |
34 |
| - entryTime: new Date().toISOString() |
35 |
| - }; |
36 |
| -} |
| 8 | +import { UserFactory } from '../user/user.factory'; |
| 9 | +import { RedisClientFactory } from '../redis/redis-client.factory'; |
37 | 10 |
|
38 | 11 | @Injectable()
|
39 |
| -export class RoomService implements OnModuleInit, OnModuleDestroy { |
40 |
| - redisAdapter: ReturnType<typeof createAdapter>; |
41 |
| - redisClient: Cluster; |
42 |
| - |
43 |
| - constructor(private redisRepository: RoomRepository) { |
44 |
| - this.redisClient = new Redis.Cluster(REDIS_CONFIG); |
45 |
| - this.redisAdapter = createAdapter(this.redisClient, this.redisClient); |
46 |
| - } |
47 |
| - |
48 |
| - async onModuleInit(){ |
49 |
| - const redisClient = new Redis.Cluster(REDIS_CONFIG); |
50 |
| - this.redisRepository.injectClient(redisClient); |
51 |
| - } |
52 |
| - |
53 |
| - async onModuleDestroy(){ |
54 |
| - if (this.redisClient) { |
55 |
| - await this.redisClient.quit(); |
56 |
| - console.log('Redis connection closed'); |
57 |
| - } |
58 |
| - } |
| 12 | +export class RoomService implements OnModuleInit { |
| 13 | + redisClient: Cluster | undefined; |
| 14 | + constructor(private readonly redisClientFactory: RedisClientFactory, private roomRepository: RoomRepository, private userFactory: UserFactory) {} |
59 | 15 |
|
60 |
| - getClient(): Cluster { |
61 |
| - return this.redisClient; |
| 16 | + async onModuleInit() { |
| 17 | + this.redisClient = this.redisClientFactory.createClient(); |
| 18 | + this.roomRepository.injectClient(this.redisClient); |
62 | 19 | }
|
63 | 20 |
|
64 |
| - getPubSubClients(): { pubClient: Cluster; subClient: Cluster } { |
65 |
| - const pubClient = this.redisClient.duplicate(); |
66 |
| - const subClient = this.redisClient.duplicate(); |
67 |
| - |
68 |
| - return { pubClient, subClient }; |
69 |
| - } |
70 |
| - |
71 |
| - get adapter(): ReturnType<typeof createAdapter> { |
72 |
| - return this.redisAdapter; |
73 |
| - } |
74 |
| - |
75 |
| - |
76 | 21 | // 방 생성
|
77 | 22 | async createRoom(roomId: string, hostId: string) {
|
78 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 23 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
79 | 24 | if (roomExists) return false;
|
80 | 25 |
|
81 | 26 | // roomId: hostId 로, room 에 hostId 지정
|
82 |
| - await this.redisRepository.createNewRoom(roomId, hostId); |
| 27 | + await this.roomRepository.createNewRoom(roomId, hostId); |
83 | 28 | console.log(`${hostId} 가 room: ${roomId} 을 만들었습니다.`);
|
84 | 29 | return true;
|
85 | 30 | }
|
86 | 31 |
|
87 | 32 | // 방 삭제
|
88 | 33 | async deleteRoom(roomId: string) {
|
89 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 34 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
90 | 35 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
91 |
| - await this.redisRepository.deleteRoom(roomId); |
| 36 | + await this.roomRepository.deleteRoom(roomId); |
92 | 37 | }
|
93 | 38 |
|
94 | 39 | async addQuestion(roomId: string, question: Omit<QuestionDto, 'questionId'>){
|
95 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 40 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
96 | 41 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
97 | 42 |
|
98 |
| - return await this.redisRepository.addQuestionToRoom(roomId, question); |
| 43 | + return await this.roomRepository.addQuestionToRoom(roomId, question); |
99 | 44 | }
|
100 | 45 |
|
101 | 46 | // 질문 추가
|
102 | 47 | async addQuestionAndReturnQuestion(
|
103 | 48 | roomId: string,
|
104 | 49 | question: Omit<QuestionDto, 'questionId'>,
|
105 | 50 | ): Promise<QuestionDto> {
|
106 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 51 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
107 | 52 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
108 | 53 |
|
109 |
| - return await this.redisRepository.addQuestionToRoom(roomId, question); |
| 54 | + return await this.roomRepository.addQuestionToRoom(roomId, question); |
110 | 55 | }
|
111 | 56 |
|
112 | 57 | // 특정 질문 완료 처리
|
113 | 58 | async markQuestionAsDone(roomId: string, questionId: number) {
|
114 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 59 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
115 | 60 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
116 | 61 |
|
117 |
| - const markedQuestion = await this.redisRepository.markQuestionAsDone(roomId, questionId); |
| 62 | + const markedQuestion = await this.roomRepository.markQuestionAsDone(roomId, questionId); |
118 | 63 | if (!markedQuestion) throw new ChatException(CHATTING_SOCKET_ERROR.QUESTION_EMPTY, roomId);
|
119 | 64 | return markedQuestion;
|
120 | 65 | }
|
121 | 66 |
|
122 | 67 | // 방에 속한 모든 질문 조회
|
123 | 68 | async getQuestions(roomId: string): Promise<QuestionDto[]> {
|
124 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 69 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
125 | 70 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
126 | 71 |
|
127 |
| - return this.redisRepository.getQuestionsAll(roomId); |
| 72 | + return this.roomRepository.getQuestionsAll(roomId); |
128 | 73 | }
|
129 | 74 |
|
130 | 75 | async getQuestionsNotDone(roomId: string): Promise<QuestionDto[]> {
|
131 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 76 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
132 | 77 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
133 | 78 |
|
134 |
| - return this.redisRepository.getQuestionsUnmarked(roomId); |
| 79 | + return this.roomRepository.getQuestionsUnmarked(roomId); |
135 | 80 | }
|
136 | 81 |
|
137 | 82 | // 특정 질문 조회
|
138 | 83 | async getQuestion(roomId: string, questionId: number): Promise<QuestionDto> {
|
139 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 84 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
140 | 85 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
141 |
| - return this.redisRepository.getQuestion(roomId, questionId); |
| 86 | + return this.roomRepository.getQuestion(roomId, questionId); |
142 | 87 | }
|
143 | 88 |
|
144 | 89 | // 유저 생성
|
145 |
| - async createUser(socket: Socket) { |
| 90 | + async addUser(socket: Socket) { |
146 | 91 | const clientId = socket.id;
|
147 | 92 | const address = socket.handshake.address.replaceAll('::ffff:', '');
|
148 | 93 | const userAgent = socket.handshake.headers['user-agent'];
|
149 | 94 |
|
150 | 95 | if(!address || !userAgent) throw new ChatException(CHATTING_SOCKET_ERROR.INVALID_USER);
|
151 | 96 |
|
152 |
| - const newUser = createRandomUserInstance(address, userAgent); |
153 |
| - const isCreatedDone = await this.redisRepository.createUser(clientId, newUser); |
| 97 | + const newUser = this.userFactory.createUserInstance(address, userAgent); |
| 98 | + const isCreatedDone = await this.roomRepository.createUser(clientId, newUser); |
154 | 99 | if(!isCreatedDone) throw new ChatException(CHATTING_SOCKET_ERROR.INVALID_USER);
|
155 | 100 | console.log(newUser);
|
156 | 101 | return newUser;
|
157 | 102 | }
|
158 | 103 |
|
159 | 104 | // 유저 삭제
|
160 | 105 | async deleteUser(clientId: string) {
|
161 |
| - return await this.redisRepository.deleteUser(clientId); |
| 106 | + return await this.roomRepository.deleteUser(clientId); |
162 | 107 | }
|
163 | 108 |
|
164 | 109 | // 특정 유저 조회
|
165 | 110 | async getUserByClientId(clientId: string) {
|
166 |
| - const user = this.redisRepository.getUser(clientId); |
| 111 | + const user = this.roomRepository.getUser(clientId); |
167 | 112 | return user;
|
168 | 113 | }
|
169 | 114 |
|
170 | 115 | async getHostOfRoom(roomId: string) {
|
171 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 116 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
172 | 117 | if (!roomExists) throw new ChatException(CHATTING_SOCKET_ERROR.ROOM_EMPTY, roomId);
|
173 |
| - return await this.redisRepository.getHost(roomId); |
| 118 | + return await this.roomRepository.getHost(roomId); |
174 | 119 | }
|
175 | 120 |
|
176 | 121 | async getUserBlacklist(roomId: string, address: string) {
|
177 |
| - const roomExists = await this.redisRepository.isRoomExisted(roomId); |
| 122 | + const roomExists = await this.roomRepository.isRoomExisted(roomId); |
178 | 123 | if (!roomExists) return [];
|
179 | 124 |
|
180 |
| - return await this.redisRepository.getUserBlacklist(roomId, address); |
| 125 | + return await this.roomRepository.getUserBlacklist(roomId, address); |
181 | 126 | }
|
182 | 127 |
|
183 | 128 | async addUserToBlacklist(roomId: string, address: string, userAgent: string){
|
184 |
| - return await this.redisRepository.addUserBlacklistToRoom(roomId, address, userAgent); |
| 129 | + return await this.roomRepository.addUserBlacklistToRoom(roomId, address, userAgent); |
185 | 130 | }
|
186 | 131 | }
|
0 commit comments