From 564dd5229a7cad98f449f7fb4880214f4a5b91e0 Mon Sep 17 00:00:00 2001 From: Seongtae Date: Mon, 5 Feb 2024 22:57:51 +0900 Subject: [PATCH 1/4] refactor: remove transaction interceptor --- src/contents/contents.controller.ts | 34 +++++------------------------ 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/src/contents/contents.controller.ts b/src/contents/contents.controller.ts index 36b56d5..a40a2e4 100644 --- a/src/contents/contents.controller.ts +++ b/src/contents/contents.controller.ts @@ -87,17 +87,11 @@ export class ContentsController { type: ErrorOutput, }) @Post('multiple') - @UseInterceptors(TransactionInterceptor) async addMultipleContents( @AuthUser() user: User, @Body() contentLinks: AddMultipleContentsBodyDto, - @TransactionManager() queryRunnerManager: EntityManager, ): Promise { - return this.contentsService.addMultipleContents( - user, - contentLinks, - queryRunnerManager, - ); + return this.contentsService.addMultipleContents(user, contentLinks); } @ApiOperation({ @@ -117,17 +111,11 @@ export class ContentsController { type: ErrorOutput, }) @Patch() - @UseInterceptors(TransactionInterceptor) async updateContent( @AuthUser() user: User, @Body() content: UpdateContentBodyDto, - @TransactionManager() queryRunnerManager: EntityManager, ): Promise { - return this.contentsService.updateContent( - user, - content, - queryRunnerManager, - ); + return this.contentsService.updateContent(user, content); } @ApiOperation({ @@ -143,17 +131,11 @@ export class ContentsController { type: ErrorOutput, }) @Patch(':contentId/favorite') - @UseInterceptors(TransactionInterceptor) async toggleFavorite( @AuthUser() user: User, - @Param('contentId', new ParseIntPipe()) contentId: number, - @TransactionManager() queryRunnerManager: EntityManager, + @Param('contentId', ParseIntPipe) contentId: number, ): Promise { - return this.contentsService.toggleFavorite( - user, - contentId, - queryRunnerManager, - ); + return this.contentsService.toggleFavorite(user, contentId); } @ApiOperation({ @@ -169,17 +151,11 @@ export class ContentsController { type: ErrorOutput, }) @Delete(':contentId') - @UseInterceptors(TransactionInterceptor) async deleteContent( @AuthUser() user: User, @Param('contentId', new ParseIntPipe()) contentId: number, - @TransactionManager() queryRunnerManager: EntityManager, ): Promise { - return this.contentsService.deleteContent( - user, - contentId, - queryRunnerManager, - ); + return this.contentsService.deleteContent(user, contentId); } @ApiOperation({ From 643dcaf87f68467c187e5873a0c9eb6f115769e8 Mon Sep 17 00:00:00 2001 From: Seongtae Date: Mon, 5 Feb 2024 22:58:10 +0900 Subject: [PATCH 2/4] feat: create save one method in content repository --- src/contents/repository/content.repository.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/contents/repository/content.repository.ts b/src/contents/repository/content.repository.ts index daf4ee4..1085624 100644 --- a/src/contents/repository/content.repository.ts +++ b/src/contents/repository/content.repository.ts @@ -1,4 +1,4 @@ -import { DataSource, Repository } from 'typeorm'; +import { DataSource, EntityManager, Repository } from 'typeorm'; import { Content } from '../entities/content.entity'; import { Injectable } from '@nestjs/common'; @@ -43,4 +43,11 @@ export class ContentRepository extends Repository { .andWhere('content.reminder < :now', { now: new Date() }) .getCount(); } + + async saveOne( + content: Content, + entityManager?: EntityManager, + ): Promise { + return entityManager ? entityManager.save(content) : this.save(content); + } } From fa457a9c4ceaa308495c6733f32195986824598e Mon Sep 17 00:00:00 2001 From: Seongtae Date: Mon, 5 Feb 2024 22:59:44 +0900 Subject: [PATCH 3/4] feat: add transactional decorator --- src/contents/contents.service.ts | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/contents/contents.service.ts b/src/contents/contents.service.ts index cdefe77..f534ac1 100644 --- a/src/contents/contents.service.ts +++ b/src/contents/contents.service.ts @@ -31,6 +31,7 @@ import { CategoryRepository } from '../categories/category.repository'; import { getLinkInfo } from './util/content.util'; import { GetLinkInfoResponseDto } from './dtos/get-link.response.dto'; import { checkContentDuplicateAndAddCategorySaveLog } from '../categories/utils/category.util'; +import { Transactional } from '../common/aop/transactional'; @Injectable() export class ContentsService { @@ -116,10 +117,11 @@ export class ContentsService { } } + @Transactional() async addMultipleContents( user: User, { contentLinks, categoryName, parentId }: AddMultipleContentsBodyDto, - queryRunnerManager: EntityManager, + entityManager?: EntityManager, ): Promise { try { const userInDb = @@ -136,7 +138,7 @@ export class ContentsService { categoryName, parentId, userInDb, - queryRunnerManager, + entityManager!, ); } for (const link of contentLinks) { @@ -152,7 +154,7 @@ export class ContentsService { ); } - const newContent = queryRunnerManager.create(Content, { + const newContent = entityManager!.create(Content, { link, title, siteName, @@ -161,10 +163,7 @@ export class ContentsService { description, user: userInDb, }); - await queryRunnerManager.save(newContent); - - // 각 링크마다 처리 후 transaction commit - await queryRunnerManager.query('COMMIT'); + await this.contentRepository.saveOne(newContent, entityManager); } } @@ -187,7 +186,7 @@ export class ContentsService { categoryName, parentId, }: UpdateContentBodyDto, - queryRunnerManager: EntityManager, + entityManager?: EntityManager, ): Promise { const newContentObj = { link, @@ -217,7 +216,7 @@ export class ContentsService { categoryName, parentId, userInDb, - queryRunnerManager, + entityManager!, ); await checkContentDuplicateAndAddCategorySaveLog( @@ -227,7 +226,7 @@ export class ContentsService { ); } - await queryRunnerManager.save(Content, [ + await entityManager!.save(Content, [ { id: content.id, ...newContentObj, ...(category && { category }) }, ]); @@ -240,7 +239,7 @@ export class ContentsService { async toggleFavorite( user: User, contentId: number, - queryRunnerManager: EntityManager, + entityManager?: EntityManager, ): Promise { try { const userInDb = await this.userRepository.findOneWithContents(user.id); @@ -258,7 +257,7 @@ export class ContentsService { } content.favorite = !content.favorite; - await queryRunnerManager.save(content); + await entityManager!.save(content); return {}; } catch (e) { @@ -269,7 +268,7 @@ export class ContentsService { async deleteContent( user: User, contentId: number, - queryRunnerManager: EntityManager, + entityManager?: EntityManager, ): Promise { try { const content = await this.contentRepository.findOneBy({ id: contentId }); @@ -284,7 +283,7 @@ export class ContentsService { } // delete content - await queryRunnerManager.delete(Content, content.id); + await entityManager!.delete(Content, content.id); return {}; } catch (e) { From bd4ee666312a0c500af12a5caea01b153fc7d8f8 Mon Sep 17 00:00:00 2001 From: Seongtae Date: Mon, 5 Feb 2024 22:59:52 +0900 Subject: [PATCH 4/4] feat: delete unused imports --- src/auth/auth.service.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 5db8160..276feff 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -8,11 +8,8 @@ import { } from '@nestjs/common'; import { Cache } from 'cache-manager'; import { v4 as uuidv4 } from 'uuid'; -import axios from 'axios'; -import * as CryptoJS from 'crypto-js'; import { MailService } from '../mail/mail.service'; -import { User } from '../users/entities/user.entity'; import { refreshTokenExpirationInCache, refreshTokenExpirationInCacheShortVersion, @@ -28,12 +25,8 @@ import { sendPasswordResetEmailOutput } from './dtos/send-password-reset-email.d import { RefreshTokenDto, RefreshTokenOutput } from './dtos/token.dto'; import { ValidateUserDto, ValidateUserOutput } from './dtos/validate-user.dto'; import { ONEYEAR, Payload } from './jwt/jwt.payload'; -import { KakaoAuthorizeOutput, LoginWithKakaoDto } from './dtos/kakao.dto'; -import { googleUserInfo } from './dtos/google.dto'; import { customJwtService } from './jwt/jwt.service'; import { UserRepository } from '../users/repository/user.repository'; -import { CategoryRepository } from '../categories/category.repository'; -import { OAuthUtil } from './util/oauth.util'; @Injectable() export class AuthService {