Skip to content

Commit 14300f2

Browse files
committed
feat: db-manager에 session 기반 DB 생성 삭제 로직 구현
1 parent db79b18 commit 14300f2

File tree

7 files changed

+264
-30
lines changed

7 files changed

+264
-30
lines changed

BE/src/record/record.service.ts

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { UsageService } from '../usage/usage.service';
1616
import { FileService } from './file.service';
1717
import { TableService } from '../table/table.service';
1818
import { ResTableDto } from '../table/dto/res-table.dto';
19-
import { Connection } from "mysql2/promise";
19+
import { Connection } from 'mysql2/promise';
2020

2121
@Injectable()
2222
export class RecordService {
@@ -30,35 +30,36 @@ export class RecordService {
3030
createRandomRecordDto: CreateRandomRecordDto,
3131
connection: Connection,
3232
) {
33-
// const tableInfo: ResTableDto = (await this.tableService.find(connection
34-
// createRandomRecordDto.tableName,
35-
// ))
36-
//
37-
// if (!tableInfo?.tableName)
38-
// throw new BadRequestException(
39-
// `${createRandomRecordDto.tableName} 테이블이 존재하지 않습니다.`,
40-
// );
41-
//
42-
// const baseColumns = tableInfo.columns;
43-
// const columnInfos: RandomColumnInfo[] = createRandomRecordDto.columns;
44-
//
45-
// columnInfos.forEach((columnInfo) => {
46-
// const targetName = columnInfo.name;
47-
// const targetDomain = columnInfo.type;
48-
// const baseColumn = baseColumns.find(
49-
// (column) => column.name === columnInfo.name,
50-
// );
51-
//
52-
// if (!baseColumn)
53-
// throw new BadRequestException(
54-
// `${targetName} 컬럼이 ${createRandomRecordDto.tableName} 에 존재하지 않습니다.`,
55-
// );
56-
//
57-
// if (!this.checkDomainAvailability(baseColumn.type, targetDomain))
58-
// throw new BadRequestException(
59-
// `${targetName}(${baseColumn.type}) 컬럼에 ${targetDomain} 랜덤 값을 넣을 수 없습니다.`,
60-
// );
61-
// });
33+
const tableInfo = await this.tableService.find(
34+
connection,
35+
createRandomRecordDto.tableName,
36+
);
37+
38+
if (!tableInfo?.tableName)
39+
throw new BadRequestException(
40+
`${createRandomRecordDto.tableName} 테이블이 존재하지 않습니다.`,
41+
);
42+
43+
const baseColumns = tableInfo.columns;
44+
const columnInfos: RandomColumnInfo[] = createRandomRecordDto.columns;
45+
46+
columnInfos.forEach((columnInfo) => {
47+
const targetName = columnInfo.name;
48+
const targetDomain = columnInfo.type;
49+
const baseColumn = baseColumns.find(
50+
(column) => column.name === columnInfo.name,
51+
);
52+
53+
if (!baseColumn)
54+
throw new BadRequestException(
55+
`${targetName} 컬럼이 ${createRandomRecordDto.tableName} 에 존재하지 않습니다.`,
56+
);
57+
58+
if (!this.checkDomainAvailability(baseColumn.type, targetDomain))
59+
throw new BadRequestException(
60+
`${targetName}(${baseColumn.type}) 컬럼에 ${targetDomain} 랜덤 값을 넣을 수 없습니다.`,
61+
);
62+
});
6263
}
6364

6465
checkDomainAvailability(mysqlType: string, targetDomain: string) {

DBManager/package-lock.json

Lines changed: 113 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DBManager/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"@nestjs/schedule": "^4.1.2",
2929
"cron": "^3.5.0",
3030
"ioredis": "^5.4.2",
31+
"mysql2": "^3.12.0",
3132
"reflect-metadata": "^0.2.0",
3233
"rxjs": "^7.8.1"
3334
},

DBManager/src/config/redis/redis.service.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ConfigService } from '@nestjs/config';
66
export class RedisService {
77
private readonly sessionConnection: Redis;
88
private readonly podConnection: Redis;
9+
private readonly sessionSubscriber: Redis;
910
private readonly activeUserSubscriber: Redis;
1011

1112
constructor(private readonly configService: ConfigService) {
@@ -21,6 +22,12 @@ export class RedisService {
2122
db: this.configService.get<number>('REDIS_DATABASE_POD'),
2223
});
2324

25+
this.sessionSubscriber = new Redis({
26+
host: this.configService.get<string>('REDIS_HOST'),
27+
port: this.configService.get<number>('REDIS_PORT'),
28+
db: this.configService.get<number>('REDIS_DATABASE_SESSION'),
29+
});
30+
2431
this.activeUserSubscriber = new Redis({
2532
host: this.configService.get<string>('REDIS_HOST'),
2633
port: this.configService.get<number>('REDIS_PORT'),
@@ -40,6 +47,16 @@ export class RedisService {
4047
await this.podConnection.hset(key, field, value);
4148
}
4249

50+
async subscribeSession(
51+
channel: string,
52+
onMessage: (message: string) => void,
53+
): Promise<void> {
54+
await this.sessionSubscriber.subscribe(channel);
55+
this.sessionSubscriber.on('message', (_, message) => {
56+
onMessage(message);
57+
});
58+
}
59+
4360
async subscribeActiveUser(
4461
channel: string,
4562
onMessage: (message: string) => void,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { ConfigService } from '@nestjs/config';
3+
import { Connection, createConnection } from 'mysql2/promise';
4+
5+
@Injectable()
6+
export class UserDBConnectionService {
7+
private connectionMap = new Map<string, Connection>();
8+
9+
constructor(private readonly configService: ConfigService) {}
10+
11+
private async getConnection(pod: string) {
12+
if (!this.connectionMap.has(pod)) {
13+
const connection = await this.createConnectionByPod(pod);
14+
this.connectionMap.set(pod, connection);
15+
}
16+
return this.connectionMap.get(pod);
17+
}
18+
19+
private async createConnectionByPod(pod: string) {
20+
return createConnection({
21+
host: pod,
22+
user: this.configService.get<string>('QUERY_DB_USER'),
23+
password: this.configService.get<string>('QUERY_DB_PASSWORD'),
24+
port: this.configService.get<number>('QUERY_DB_PORT'),
25+
});
26+
}
27+
28+
public async initUserDatabase(pod: string, sessionId: string) {
29+
try {
30+
const identify = sessionId.substring(0, 10);
31+
const connectInfo = {
32+
name: identify,
33+
password: identify,
34+
host: '%',
35+
database: identify,
36+
};
37+
38+
const connection = await this.getConnection(pod);
39+
40+
await connection.query(`create database ${connectInfo.database};`);
41+
await connection.query(
42+
`create user '${connectInfo.name}'@'${connectInfo.host}' identified by '${connectInfo.password}';`,
43+
);
44+
await connection.query(
45+
`grant all privileges on ${connectInfo.database}.* to '${connectInfo.name}'@'${connectInfo.host}';`,
46+
);
47+
} catch (e) {
48+
console.error(e);
49+
}
50+
}
51+
52+
public async removeDatabase(pod: string, sessionId: string) {
53+
try {
54+
const connection = await this.getConnection(pod);
55+
56+
const identify = sessionId.substring(0, 10);
57+
58+
const dropDatabase = `drop database ${identify}`;
59+
await connection.query(dropDatabase);
60+
const dropUser = `drop user '${identify}'`;
61+
await connection.query(dropUser);
62+
} catch (e) {
63+
console.error(e);
64+
}
65+
}
66+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Module } from '@nestjs/common';
2+
import { UserSessionDBService } from './user-session-db.service';
3+
4+
@Module({
5+
providers: [UserSessionDBService],
6+
})
7+
export class UserDBModule {}

0 commit comments

Comments
 (0)