From 639b19c5ee650249d24c0f45b9ac71f5343de37d Mon Sep 17 00:00:00 2001 From: jinddings Date: Thu, 14 Nov 2024 14:51:19 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20feat=20:=20redis=EC=97=90=20=20?= =?UTF-8?q?=EC=B5=9C=EA=B7=BC=20=EA=B2=80=EC=83=89=EC=96=B4=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20Controller?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC(#57)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../list/interface/search-params.interface.ts | 2 +- BE/src/stock/list/stock-list.controller.ts | 51 +++++++++++++++++-- BE/src/stock/list/stock-list.service.ts | 23 ++++++--- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/BE/src/stock/list/interface/search-params.interface.ts b/BE/src/stock/list/interface/search-params.interface.ts index 879f55b9..2f0b205b 100644 --- a/BE/src/stock/list/interface/search-params.interface.ts +++ b/BE/src/stock/list/interface/search-params.interface.ts @@ -2,5 +2,5 @@ export interface SearchParams { name?: string; market?: string; code?: string; - userId: number; + userId?: string; } diff --git a/BE/src/stock/list/stock-list.controller.ts b/BE/src/stock/list/stock-list.controller.ts index d7272784..4c484cb1 100644 --- a/BE/src/stock/list/stock-list.controller.ts +++ b/BE/src/stock/list/stock-list.controller.ts @@ -1,5 +1,12 @@ -import { Controller, Get, Query, Req, UseGuards } from '@nestjs/common'; -import { ApiOperation, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { Controller, Get, Post, Query, Req, UseGuards } from '@nestjs/common'; +import { + ApiBearerAuth, + ApiBody, + ApiOperation, + ApiQuery, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; import { Request } from 'express'; import { JwtAuthGuard } from 'src/auth/jwt-auth-guard'; import { StockListService } from './stock-list.service'; @@ -36,13 +43,11 @@ export class StockListController { @Get('/search') @UseGuards(JwtAuthGuard) async searchWithQuery( - @Req() req: Request, @Query('name') name?: string, @Query('market') market?: string, @Query('code') code?: string, ): Promise { - const userId = parseInt(req.user.userId, 10); - return this.stockListService.search({ name, market, code, userId }); + return this.stockListService.search({ name, market, code }); } @ApiOperation({ @@ -58,4 +63,40 @@ export class StockListController { async findOne(@Query('code') code: string): Promise { return this.stockListService.findOne(code); } + + @Post('/search/addHistory') + @UseGuards(JwtAuthGuard) + @ApiOperation({ + summary: '검색어 히스토리 추가 API', + description: '특정 유저의 검색어 히스토리를 추가한다.', + }) + @ApiBody({ + schema: { + type: 'object', + properties: { + searchTerm: { type: 'string' }, + }, + }, + }) + @ApiBearerAuth() + async addSearchHistory(@Req() req: Request) { + const { searchTerm } = req.body; + const userId = parseInt(req.user.userId, 10); + await this.stockListService.addSearchTermToRedis({ + searchTerm, + userId, + }); + } + + @Get('/search/getHistory') + @UseGuards(JwtAuthGuard) + @ApiOperation({ + summary: '검색어 히스토리 조회 API', + description: '특정 유저의 검색어 히스토리를 조회한다.', + }) + @ApiBearerAuth() + async getSearchHistory(@Req() req: Request) { + const userId = req.user.userId; + return this.stockListService.getSearchTermFromRedis(userId); + } } diff --git a/BE/src/stock/list/stock-list.service.ts b/BE/src/stock/list/stock-list.service.ts index 9d61f15a..5916b210 100644 --- a/BE/src/stock/list/stock-list.service.ts +++ b/BE/src/stock/list/stock-list.service.ts @@ -33,19 +33,18 @@ export class StockListService { } async search(params: SearchParams): Promise { - await this.addSearchTermToRedis(params); const stocks = await this.stockListRepository.search(params); return stocks.map((stock) => this.toResponseDto(stock)); } - async addSearchTermToRedis(params: SearchParams) { - const key = `search:${params.userId}`; + async addSearchTermToRedis(searchInfo: { + userId: Number; + searchTerm: string; + }) { + const { userId, searchTerm } = searchInfo; + const key = `search:${userId}`; const timeStamp = Date.now(); - const { name, market, code } = params; - - const searchTerm = name || market || code; - await this.redisDomainService.zadd(key, timeStamp, searchTerm); const searchHistoryCount = await this.redisDomainService.zcard(key); @@ -53,4 +52,14 @@ export class StockListService { await this.redisDomainService.zremrangebyrank(key, 0, 0); } } + + async getSearchTermFromRedis(userId: string): Promise { + const key = `search:${userId}`; + + return await this.redisDomainService.zrevrange( + key, + 0, + this.SearchHistoryLimit - 1, + ); + } } From 949f3984da63b41b525e258602823d0d43f15e08 Mon Sep 17 00:00:00 2001 From: jinddings Date: Thu, 14 Nov 2024 15:09:31 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=A8=20feat=20:=20=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=8B=9C=EC=97=90=20=20redis=20container=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=EB=B0=8F=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deply-alpha.yml | 10 ++++++++++ BE/docker-compose.yml | 27 +++++++++++++++++++++++++++ BE/src/common/redis/redis.module.ts | 4 ++-- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 BE/docker-compose.yml diff --git a/.github/workflows/deply-alpha.yml b/.github/workflows/deply-alpha.yml index ec6ec9ce..496c289a 100644 --- a/.github/workflows/deply-alpha.yml +++ b/.github/workflows/deply-alpha.yml @@ -106,11 +106,21 @@ jobs: docker system prune -af echo "${{ secrets.ENV }}" > .env + docker network create juga-network || true + + docker run -d \ + --name redis \ + --network juga-network \ + -p 6379:6379 \ + -v redis_data:/data \ + redis:latest redis-server --appendonly yes + docker pull ${{ env.DOCKER_IMAGE }}-${{ matrix.app.name }}:${{ env.DOCKER_TAG }} docker stop ${{ matrix.app.container }} || true docker rm ${{ matrix.app.container }} || true docker run -d \ --name ${{ matrix.app.container }} \ + --network juga-network \ -p ${{ matrix.app.port }}:${{ matrix.app.port }} \ --env-file .env \ ${{ env.DOCKER_IMAGE }}-${{ matrix.app.name }}:${{ env.DOCKER_TAG }} diff --git a/BE/docker-compose.yml b/BE/docker-compose.yml new file mode 100644 index 00000000..37d586f9 --- /dev/null +++ b/BE/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3' +services: + api: + build: + context: . + dockerfile: Dockerfile + ports: + - '3000:3000' + environment: + - NODE_ENV=production + - REDIS_HOST=redis + - REDIS_PORT=6379 + depends_on: + - redis + restart: unless-stopped + + redis: + image: redis:latest + ports: + - '6379:6379' + volumes: + - redis_data:/data + command: redis-server --appendonly yes + restart: unless-stopped + +volumes: + redis_data: diff --git a/BE/src/common/redis/redis.module.ts b/BE/src/common/redis/redis.module.ts index a0cf55bc..863812b5 100644 --- a/BE/src/common/redis/redis.module.ts +++ b/BE/src/common/redis/redis.module.ts @@ -10,8 +10,8 @@ import { RedisDomainService } from './redis.domain-service'; provide: 'REDIS_CLIENT', useFactory: () => { return new Redis({ - host: process.env.REDIS_HOST, - port: Number(process.env.REDIS_PORT), + host: process.env.REDIS_HOST || 'redis', + port: Number(process.env.REDIS_PORT || 6379), }); }, }, From 6e73abe00b3e00601d8f594230ba94a51bdbf7f9 Mon Sep 17 00:00:00 2001 From: jinddings Date: Thu, 14 Nov 2024 15:12:38 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=94=A7=20fix=20:=20:Production=20Yml?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EB=8F=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-production.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml index c2cde28f..fea0130d 100644 --- a/.github/workflows/deploy-production.yml +++ b/.github/workflows/deploy-production.yml @@ -106,15 +106,23 @@ jobs: docker system prune -af echo "${{ secrets.ENV }}" > .env + docker network create juga-network || true + + docker run -d \ + --name redis \ + --network juga-network \ + -p 6379:6379 \ + -v redis_data:/data \ + redis:latest redis-server --appendonly yes + docker pull ${{ env.DOCKER_IMAGE }}-${{ matrix.app.name }}:${{ env.DOCKER_TAG }} docker stop ${{ matrix.app.container }} || true docker rm ${{ matrix.app.container }} || true docker run -d \ --name ${{ matrix.app.container }} \ + --network juga-network \ -p ${{ matrix.app.port }}:${{ matrix.app.port }} \ --env-file .env \ - -v /etc/localtime:/etc/localtime:ro \ - -e TZ=Asia/Seoul \ ${{ env.DOCKER_IMAGE }}-${{ matrix.app.name }}:${{ env.DOCKER_TAG }} - name: Remove Github Action Ip to Security group