-
Notifications
You must be signed in to change notification settings - Fork 0
Issue/199/redis multi instance #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
2fa4438
9fe4ad1
c78a055
7178df6
aa4782a
5eb97d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
version: '3' | ||
|
||
services: | ||
rabbitmq: | ||
image: rabbitmq:3-management | ||
container_name: rabbitmq | ||
ports: | ||
- '5672:5672' # AMQP 프로토콜 (앱들이 사용하는 포트) | ||
- '15672:15672' # 관리 콘솔 (웹 UI) 포트 | ||
env_file: '../../env/.env.dev' | ||
environment: | ||
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} | ||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS} | ||
volumes: | ||
- rabbitmq-data:/var/lib/rabbitmq | ||
restart: unless-stopped | ||
|
||
volumes: | ||
rabbitmq-data: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
docker compose --env-file=../../env/.env.dev up -d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: '3.8' | ||
|
||
services: | ||
redis-MQ: | ||
image: redis:7.2-alpine | ||
container_name: redis | ||
ports: | ||
- '6379:6379' | ||
volumes: | ||
- ./redis.conf:/usr/local/etc/redis/redis.conf | ||
- ./redis-data:/data | ||
command: ['redis-server', '/usr/local/etc/redis/redis.conf'] | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: '3.8' | ||
|
||
services: | ||
redis-MQ: | ||
image: redis:7.2-alpine | ||
container_name: redis-mq | ||
ports: | ||
- '6379:6379' | ||
volumes: | ||
- ./redis.conf:/usr/local/etc/redis/redis.conf | ||
- ./redis-data:/data | ||
command: ['redis-server', '/usr/local/etc/redis/redis.conf'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드 패치 리뷰
이러한 이유들로 인해 현재 이 코드는 병합되기에 위험 요소가 존재합니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,4 +44,6 @@ lerna-debug.log* | |
|
||
apps/server/volumes | ||
volumes | ||
.clinic | ||
|
||
# redis | ||
.docker/redis/redis-data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 코드 수정사항은 몇 가지 문제를 안고 있습니다. 첫째, |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,14 @@ | ||
import { createKeyv } from '@keyv/redis' | ||
import { CacheModule } from '@nestjs/cache-manager' | ||
import { Module } from '@nestjs/common' | ||
import { APP_GUARD } from '@nestjs/core' | ||
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core' | ||
import { JwtService } from '@nestjs/jwt' | ||
import { ClsPluginTransactional } from '@nestjs-cls/transactional' | ||
import { TransactionalAdapterPrisma } from '@nestjs-cls/transactional-adapter-prisma' | ||
import { ClsModule } from 'nestjs-cls' | ||
|
||
import { LoggingInterceptor } from '@otl/common/logger/logging.interceptor' | ||
|
||
import { PrismaModule } from '@otl/prisma-client/prisma.module' | ||
import { PrismaService } from '@otl/prisma-client/prisma.service' | ||
|
||
|
@@ -65,6 +69,12 @@ import settings from './settings' | |
}), | ||
], | ||
}), | ||
CacheModule.registerAsync({ | ||
useFactory: async () => ({ | ||
stores: [createKeyv(settings().getRedisConfig().url)], | ||
}), | ||
isGlobal: true, | ||
}), | ||
], | ||
controllers: [AppController], | ||
providers: [ | ||
|
@@ -77,6 +87,10 @@ import settings from './settings' | |
}, | ||
inject: [AuthConfig], | ||
}, | ||
{ | ||
provide: APP_INTERCEPTOR, | ||
useClass: LoggingInterceptor, | ||
}, | ||
JwtCookieGuard, | ||
MockAuthGuard, | ||
AppService, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드 리뷰
이러한 사항들을 고려한 후 다시 검토할 것을 권장드립니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,16 @@ | ||
import { ValidationPipe, VersioningType } from '@nestjs/common' | ||
import { HttpException, ValidationPipe, VersioningType } from '@nestjs/common' | ||
import { NestFactory } from '@nestjs/core' | ||
import cookieParser from 'cookie-parser' | ||
import csrf from 'csurf' | ||
import { json } from 'express' | ||
import session from 'express-session' | ||
import fs from 'fs' | ||
import morgan from 'morgan' | ||
import * as v8 from 'node:v8' | ||
import { join } from 'path' | ||
import * as swaggerUi from 'swagger-ui-express' | ||
|
||
import { HttpExceptionFilter, UnexpectedExceptionFilter } from '@otl/common/exception/exception.filter' | ||
|
||
import { AppModule } from '../app.module' | ||
import settings from '../settings' | ||
|
||
|
@@ -43,30 +44,7 @@ async function bootstrap() { | |
ignoreMethods: ['GET', 'HEAD', 'OPTIONS', 'DELETE', 'PATCH', 'PUT', 'POST'], | ||
}), | ||
) | ||
// Logs requests | ||
app.use( | ||
morgan(':method :url OS/:req[client-os] Ver/:req[client-api-version]', { | ||
// https://github.com/expressjs/morgan#immediate | ||
immediate: true, | ||
stream: { | ||
write: (message) => { | ||
console.info(message.trim()) | ||
}, | ||
}, | ||
}), | ||
) | ||
|
||
// Logs responses | ||
// app.use( | ||
// morgan(':method :url :status :res[content-length] :response-time ms', { | ||
// stream: { | ||
// write: (message) => { | ||
// // console.log(formatMemoryUsage()) | ||
// console.info(message.trim()); | ||
// }, | ||
// }, | ||
// }), | ||
// ); | ||
if (process.env.NODE_ENV !== 'prod') { | ||
const swaggerJsonPath = join(__dirname, '..', '..', 'docs', 'swagger.json') | ||
const swaggerDocument = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf-8')) | ||
|
@@ -83,6 +61,7 @@ async function bootstrap() { | |
|
||
app.use('/api/sync', json({ limit: '50mb' })) | ||
app.use(json({ limit: '100kb' })) | ||
app.useGlobalFilters(new UnexpectedExceptionFilter(), new HttpExceptionFilter<HttpException>()) | ||
console.log(v8.getHeapStatistics().heap_size_limit / 1024 / 1024) | ||
|
||
app.enableShutdownHooks() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다음과 같은 몇 가지 사항을 고려해야 합니다:
해결해야 할 이슈와 함께 코드 품질을 향상시키기 위한 방법을 고려하십시오. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { CacheInterceptor } from '@nestjs/cache-manager' | ||
import { ExecutionContext, Injectable } from '@nestjs/common' | ||
|
||
/** | ||
* @Todo | ||
* 예시로 일단 인터넷에 있는거 긁어온거임. | ||
* 적절히 구현 변형 필요 | ||
*/ | ||
|
||
const excludePaths = [ | ||
// 캐시가 적용되지 않아야 할 path 목록 () | ||
/(\/sample2\/)(.*)/i, | ||
] | ||
|
||
@Injectable() | ||
export class HttpCacheInterceptor extends CacheInterceptor { | ||
trackBy(context: ExecutionContext): string | undefined { | ||
const request = context.switchToHttp().getRequest() | ||
const { query } = request | ||
const { httpAdapter } = this.httpAdapterHost | ||
|
||
// Get Request가 아닌 request 처리 | ||
const isGetRequest = httpAdapter.getRequestMethod(request) === 'GET' | ||
if (!isGetRequest) { | ||
return undefined | ||
} | ||
|
||
// noCache=true query parameter 처리 | ||
const noCache = query.noCache && query.noCache.toLowerCase() === 'true' | ||
if (noCache) { | ||
return undefined | ||
} | ||
|
||
// 설정된 캐시 예외 path 처리 | ||
const requestPath = httpAdapter.getRequestUrl(request).split('?')[0] | ||
const exclude = excludePaths.find((path) => path.test(requestPath)) | ||
if (exclude) { | ||
return undefined | ||
} | ||
|
||
return httpAdapter.getRequestUrl(request) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 코드 패치는 HttpCacheInterceptor를 구현하였으나, 몇 가지 문제점과 개선 사항이 있습니다.
위 사항들을 종합적으로 고려하여 수정 후 다시 검토하는 것이 좋겠습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,24 @@ | ||
import { CacheInterceptor, CacheTTL } from '@nestjs/cache-manager' | ||
import { | ||
BadRequestException, Controller, Get, Param, Post, Query, | ||
BadRequestException, Controller, Get, Param, Post, Query, UseInterceptors, | ||
} from '@nestjs/common' | ||
import { GetUser } from '@otl/server-nest/common/decorators/get-user.decorator' | ||
import { Public } from '@otl/server-nest/common/decorators/skip-auth.decorator' | ||
import { ICourse, ILecture, IReview } from '@otl/server-nest/common/interfaces' | ||
import { CourseIdPipe } from '@otl/server-nest/common/pipe/courseId.pipe' | ||
import { session_userprofile } from '@prisma/client' | ||
|
||
import { RedisTTL } from '@otl/common/enum/time' | ||
|
||
import { CoursesService } from './courses.service' | ||
|
||
@Controller('api/courses') | ||
export class CourseController { | ||
constructor(private readonly coursesService: CoursesService) {} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get() | ||
async getCourses( | ||
@Query() query: ICourse.Query, | ||
|
@@ -24,12 +29,16 @@ export class CourseController { | |
} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get('autocomplete') | ||
async getCourseAutocomplete(@Query() query: ICourse.AutocompleteQueryDto): Promise<string | undefined> { | ||
return await this.coursesService.getCourseAutocomplete(query) | ||
} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get(':id') | ||
async getCourseById( | ||
@Param('id', CourseIdPipe) id: number, | ||
|
@@ -40,6 +49,8 @@ export class CourseController { | |
} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get(':id/lectures') | ||
async getLecturesByCourseId( | ||
@Query() query: ICourse.LectureQueryDto, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드 리뷰 코멘트이 코드 패치는 전반적으로 잘 작성되었으나 몇 가지 고려할 점과 잠재적인 위험이 있습니다. 다음은 세부 사항입니다:
이러한 고려 사항을 해결하면 코드의 품질과 안정성을 향상시킬 수 있습니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,39 @@ | ||
import { CacheInterceptor, CacheTTL } from '@nestjs/cache-manager' | ||
import { | ||
Controller, Get, Param, Query, | ||
Controller, Get, Param, Query, UseInterceptors, | ||
} from '@nestjs/common' | ||
import { GetUser } from '@otl/server-nest/common/decorators/get-user.decorator' | ||
import { Public } from '@otl/server-nest/common/decorators/skip-auth.decorator' | ||
import { ILecture, IReview } from '@otl/server-nest/common/interfaces' | ||
import { session_userprofile } from '@prisma/client' | ||
|
||
import { RedisTTL } from '@otl/common/enum/time' | ||
|
||
import { LecturesService } from './lectures.service' | ||
|
||
@Controller('api/lectures') | ||
export class LecturesController { | ||
constructor(private readonly LectureService: LecturesService) {} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get() | ||
async getLectures(@Query() query: ILecture.QueryDto): Promise<ILecture.Detail[]> { | ||
return await this.LectureService.getLectureByFilter(query) | ||
} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get('autocomplete') | ||
async getLectureAutocomplete(@Query() query: ILecture.AutocompleteQueryDto): Promise<string | undefined> { | ||
return await this.LectureService.getLectureAutocomplete(query) | ||
} | ||
|
||
@Public() | ||
@CacheTTL(RedisTTL.HOUR) | ||
@UseInterceptors(CacheInterceptor) | ||
@Get(':id') | ||
async getLectureById(@Param('id') id: number): Promise<ILecture.Detail> { | ||
return await this.LectureService.getLectureById(id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드 리뷰
이렇듯 코드에 수정할 부분이 존재하므로, 현재 상태에서는 머지할 준비가 되었다고 보기 어렵습니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,6 +63,10 @@ const getPrismaConfig = (): Prisma.PrismaClientOptions => ({ | |
], | ||
}) | ||
|
||
const getRedisConfig = () => ({ | ||
url: process.env.REDIS_URL, | ||
}) | ||
|
||
const getReplicatedPrismaConfig = (): Prisma.PrismaClientOptions => ({}) | ||
|
||
const getAWSConfig = () => ({}) | ||
|
@@ -106,6 +110,7 @@ export default () => ({ | |
ormconfig: () => getPrismaConfig(), | ||
ormReplicatedConfig: () => getReplicatedPrismaConfig(), | ||
awsconfig: () => getAWSConfig(), | ||
getRedisConfig: () => getRedisConfig(), | ||
getJwtConfig: () => getJwtConfig(), | ||
getSsoConfig: () => getSsoConfig(), | ||
getCorsConfig: () => getCorsConfig(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 코드 패치에는 몇 가지 잠재적인 문제가 있습니다.
따라서, 위의 사항들을 고려하여 수정한다면 코드의 안정성과 가독성을 향상시킬 수 있을 것입니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ RUN mkdir -p /var/www/otlplus | |
RUN mkdir -p /var/www/otlplus/libs | ||
RUN mkdir -p /var/www/otlplus/apps | ||
WORKDIR /var/www/otlplus | ||
RUN mkdir -p /var/www/otlplus/apps/scholar-sync/logs | ||
|
||
|
||
COPY package.json yarn.lock* package-lock.json* tsconfig.json tsconfig.build.json ./ | ||
COPY nest-cli.json ./ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 패치에서 몇 가지 우려사항이 있습니다:
따라서, 위의 문제들을 수정한 후에 다시 검토하는 것이 좋습니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ RUN mkdir -p /var/www/otlplus-server | |
RUN mkdir -p /var/www/otlplus-server/libs | ||
RUN mkdir -p /var/www/otlplus-server/apps | ||
WORKDIR /var/www/otlplus-server | ||
RUN mkdir -p /var/www/otlplus-server/apps/server/logs | ||
|
||
|
||
COPY package.json yarn.lock* package-lock.json* tsconfig.json tsconfig.build.json ./ | ||
COPY nest-cli.json ./ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드 리뷰
위의 문제를 고려했을 때, 코드에 약간의 위험 요소가 포함되어 있어 현재 상태에서는 병합에 주의가 필요합니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,5 +21,6 @@ services: | |
- '8000' | ||
volumes: | ||
- '/etc/timezone:/etc/timezone:ro' | ||
- './apps/server/logs:/var/www/otlplus-server/apps/server/logs' | ||
working_dir: /var/www/otlplus-server | ||
command: pm2-runtime start ecosystem.config.js --only @otl/server-nest --node-args="max-old-space-size=40920" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수정 사항에 대해 몇 가지 잠재적인 문제가 있습니다. 추가된 로그 디렉토리 마운트 경로 './apps/server/logs'가 실제로 존재하는지 확인해야 합니다. 존재하지 않는 경로를 마운트하려고 하면 런타임 에러가 발생할 수 있습니다. 이 경로의 존재 여부를 확인하고, 필요한 경우 사전 생성하도록 문서화하는 것이 좋습니다. 또한, 볼륨 마운트는 보안 및 성능 측면에서 주의해야 하므로, 로그 데이터의 크기와 저장 정책에 대해 검토할 필요가 있습니다. 마지막으로, command 줄에서 메모리 제한을 40920MB로 설정하는 부분은 일반적으로 비정상적으로 큰 값입니다. 이 값을 실제 필요에 따라 조정해야 할 수 있습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,5 +21,6 @@ services: | |
- '8000' | ||
volumes: | ||
- '/etc/timezone:/etc/timezone:ro' | ||
- './apps/server/logs:/var/www/otlplus-server/apps/server/logs' | ||
working_dir: /var/www/otlplus-server | ||
command: pm2-runtime start ecosystem.config.js --only @otl/server-nest --node-args="max-old-space-size=40920" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다음 사항들을 고려할 필요가 있습니다:
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,5 +19,6 @@ services: | |
- '58000:8000' | ||
volumes: | ||
- '/etc/timezone:/etc/timezone:ro' | ||
- './apps/server/logs:/var/www/otlplus-server/apps/server/logs' | ||
working_dir: /var/www/otlplus-server | ||
command: pm2-runtime start ecosystem.config.js --only @otl/server-nest --node-args="max-old-space-size=40920" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드 검토 코멘트
결론적으로, 제안한 변경 사항은 적절해 보이나, 경로 확인 및 보안 측면에서 추가 검토가 필요합니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const RedisTTL = { | ||
DAY: 3600 * 24 * 1000, | ||
WEEK: 3600 * 24 * 7 * 1000, | ||
HOUR: 3600 * 1000, | ||
HALF_HOUR: 1800 * 1000, | ||
MIN: 60 * 1000, | ||
} as const | ||
export type TTL = (typeof RedisTTL)[keyof typeof RedisTTL] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드에서 몇 가지 잠재적인 문제가 발견되었습니다. 아래는 개선 제안입니다:
이러한 주요 사항을 확인한 후에는 병합이 가능할 것입니다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드 리뷰 코멘트
버전:
version: '3.8'
이 사용되었는데, 이는 Docker Compose v3.x의 버전입니다. 현재 후방 호환성을 위해 더 오래된 버전이 필요할 수 있습니다.서비스 이름:
redis-MQ
라는 서비스 이름은 다소 혼동을 줄 수 있습니다. Redis는 메시지 큐로 사용되지만, 사용자에게 이를 명확히 하기 위해 간단하게redis
로 변경하는 것이 좋습니다.컨테이너 이름:
container_name: redis
는 데이터베이스가 많은 환경에서 네임 충돌을 초래할 가능성이 있습니다.container_name
을 고유하게 설정해주는 것이 좋습니다.포트 설정: 포트를 노출할 때 보안 고려가 필요합니다. 만약 사용하지 않는 환경이라면 포트를 막는 것이 좋습니다.
볼륨 경로:
./redis.conf
와./redis-data
는 상대 경로입니다. 이 경로가 정확한지 확인해야 하며, 운영 환경에서 이로 인해 발생할 수 있는 문제가 없는지 검토해야 합니다.커맨드:
command
에 사용된 경로/usr/local/etc/redis/redis.conf
가 컨테이너 내에서 정확한 경로인지 확인이 필요합니다. 만약 잘못되면 Redis가 시작되지 않을 수 있습니다.Redis 설정 파일:
redis.conf
에서 추가적인 설정이 필요할 수 있습니다. 예를 들어, 보안과 관련된 설정(비밀번호 설정 등)이 필요할 수 있습니다.다시 말해, 주요 문제는 서비스 이름과 경로 확인에 있으며, 더욱 안전한 설정을 적용하는 것이 필요합니다.