Skip to content

Commit

Permalink
Merge pull request #268 from Quickchive/refactor/#263-delete-type-ass…
Browse files Browse the repository at this point in the history
…ertion-contents-in-add-category

refactor: delete type assertion contents in add category
  • Loading branch information
stae1102 authored Feb 11, 2024
2 parents a2511d3 + 3abfce6 commit 5057317
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 95 deletions.
23 changes: 12 additions & 11 deletions src/categories/category.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,35 @@ export class Category extends CoreEntity {
@Column()
@IsString()
@Length(2)
name!: string;
name: string;

@ApiProperty({ description: 'Category Slug' })
@Column()
@IsString()
slug!: string;
slug: string;

@OneToMany((type) => Content, (content) => content.category)
contents!: Content[];
@OneToMany(() => Content, (content) => content.category)
contents: Content[];

@Column({ type: 'enum', enum: IconName, default: IconName.None })
@IsEnum(IconName)
iconName!: IconName;
iconName?: IconName;

@OneToMany((type) => Collection, (collection) => collection.category)
collections!: Collection[];
@OneToMany(() => Collection, (collection) => collection.category)
collections: Collection[];

@ApiProperty({ description: 'Category Parent ID', example: 1, type: Number })
@Column({ type: 'int', nullable: true })
parentId?: number | null;
parentId?: number;

@ManyToOne((type) => User, (user) => user.categories, {
@ManyToOne(() => User, (user) => user.categories, {
onDelete: 'CASCADE',
nullable: false,
lazy: true,
})
user!: User;
user: User;

@ApiProperty({ description: 'Owner ID' })
@RelationId((category: Category) => category.user)
userId!: number;
userId: number;
}
46 changes: 20 additions & 26 deletions src/categories/category.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,20 @@ export class CategoryRepository extends Repository<Category> {
super(Category, dataSource.createEntityManager());
}

async findParentCategory(
parentId: number,
async findById(
id: number,
entityManager?: EntityManager,
): Promise<Category | null> {
return (
(await entityManager?.findOneBy(Category, { id: parentId })) ??
(await this.findOneBy({ id: parentId }))
);
return entityManager
? entityManager.findOneBy(Category, { id })
: this.findOneBy({ id });
}

async createOne(
category: Category,
category: Category & { parentId?: number },
entityManager?: EntityManager,
): Promise<Category> {
return (await entityManager?.save(category)) ?? (await this.save(category));
return entityManager ? entityManager?.save(category) : this.save(category);
}

/**
Expand All @@ -45,7 +44,7 @@ export class CategoryRepository extends Repository<Category> {
categoryName: string,
parentId: number | undefined,
userInDb: User,
queryRunnerManager: EntityManager,
entityManager?: EntityManager,
): Promise<Category> {
// generate category name and slug
const { categorySlug } = generateSlug(categoryName);
Expand All @@ -56,9 +55,7 @@ export class CategoryRepository extends Repository<Category> {
let parentCategory: Category | null;
for (let i = 0; i < 2; i++) {
if (currentParentId === null) break;
parentCategory = await queryRunnerManager.findOne(Category, {
where: { id: currentParentId },
});
parentCategory = await this.findById(currentParentId, entityManager);
if (i === 1 && parentCategory?.parentId !== null) {
throw new ConflictException('Category depth should be 3');
}
Expand All @@ -68,7 +65,7 @@ export class CategoryRepository extends Repository<Category> {
}
}
// check if category exists in user's categories
let category: Category | undefined = userInDb.categories?.find(
const category = userInDb.categories?.find(
(category) =>
category.slug === categorySlug && category.parentId == parentId,
);
Expand All @@ -77,26 +74,23 @@ export class CategoryRepository extends Repository<Category> {
if (!category) {
// if parent id exists, get parent category
const parentCategory: Category | null = parentId
? await queryRunnerManager.findOne(Category, {
where: { id: parentId },
})
? await this.findById(parentId, entityManager)
: null;
// if parent category doesn't exist, throw error
if (!parentCategory && parentId) {
throw new NotFoundException('Parent category not found');
}

category = await queryRunnerManager.save(
queryRunnerManager.create(Category, {
slug: categorySlug,
name: categoryName,
parentId: parentCategory?.id,
user: userInDb,
}),
);
const newCategory = new Category();
newCategory.slug = categorySlug;
newCategory.name = categoryName;
newCategory.parentId = parentCategory?.id;
newCategory.user = userInDb;

await this.createOne(newCategory, entityManager);
userInDb.categories?.push(newCategory);

userInDb.categories?.push(category);
await queryRunnerManager.save(userInDb);
return newCategory;
}

return category;
Expand Down
6 changes: 3 additions & 3 deletions src/categories/category.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class CategoryService {
let currentParentId: number | undefined = parentId;
let parentCategory: Category | null;
for (let i = 0; i < 2; i++) {
parentCategory = await this.categoryRepository.findParentCategory(
parentCategory = await this.categoryRepository.findById(
currentParentId,
entityManager,
);
Expand Down Expand Up @@ -103,7 +103,7 @@ export class CategoryService {
} else {
// if parent category exists, get parent category
const parentCategory: Category | null = parentId
? await this.categoryRepository.findParentCategory(parentId)
? await this.categoryRepository.findById(parentId)
: null;
// if parent category doesn't exist, throw error
if (!parentCategory && parentId) {
Expand Down Expand Up @@ -248,7 +248,7 @@ export class CategoryService {

await queryRunnerManager.save(
childrenCategories.map((childrenCategory) => {
childrenCategory.parentId = parentCategory?.id ?? null;
childrenCategory.parentId = parentCategory?.id;
return childrenCategory;
}),
);
Expand Down
13 changes: 12 additions & 1 deletion src/categories/utils/category.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,18 @@ export const checkContentDuplicateAndAddCategorySaveLog = async (
},"savedAt": ${new Date().getTime()}}\n`;

// 유저 로그 파일에 로그 추가
fs.appendFileSync(`${__dirname}/../../../user_logs/${userInDb.id}.txt`, log);
new Promise<void>((resolve, reject) => {
fs.appendFile(
`${__dirname}/../../../user_logs/${userInDb.id}.txt`,
log,
(err) => {
if (err) {
reject();
}
resolve();
},
);
});
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/common/interceptors/timeout.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { catchError, timeout } from 'rxjs/operators';
export class TimeoutInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
timeout(5000),
timeout(7000), // TODO 크롤링 시 응답이 오래 걸릴 수 있으므로, API 별 인터셉터 오버라이딩 필요
catchError((err) => {
if (err instanceof TimeoutError) {
console.log(err);
Expand Down
90 changes: 39 additions & 51 deletions src/contents/contents.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class ContentsService {
private readonly dataSource: DataSource,
) {}

@Transactional()
async addContent(
user: User,
{
Expand All @@ -54,67 +55,54 @@ export class ContentsService {
categoryName,
parentId,
}: AddContentBodyDto,
entityManager?: EntityManager,
): Promise<AddContentOutput> {
const userInDb = await this.userRepository.findOneWithContentsAndCategories(
user.id,
);
if (!userInDb) {
throw new NotFoundException('User not found');
}
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();

try {
// get og tag info from link
const {
title: linkTitle,
siteName,
description,
coverImg,
} = await getLinkInfo(link);
title = title ? title : linkTitle;

let category: Category | null = null;
if (categoryName) {
category = await this.categoryRepository.getOrCreateCategory(
// TODO 명령과 조회를 분리
categoryName,
parentId,
userInDb,
queryRunner.manager,
);

await checkContentDuplicateAndAddCategorySaveLog(
link,
category,
userInDb,
);
}
const {
title: linkTitle,
siteName,
description,
coverImg,
} = await getLinkInfo(link);
title = title ? title : linkTitle;

let category: Category | undefined = undefined;
if (categoryName) {
category = await this.categoryRepository.getOrCreateCategory(
// TODO 명령과 조회를 분리
categoryName,
parentId,
userInDb,
entityManager,
);

const newContent = queryRunner.manager.create(Content, {
await checkContentDuplicateAndAddCategorySaveLog(
link,
title,
siteName,
coverImg,
description,
comment,
reminder,
...(category && { category }),
user,
...(favorite && { favorite }),
});
await queryRunner.manager.save(newContent);

await queryRunner.commitTransaction();

return {};
} catch (e) {
await queryRunner.rollbackTransaction();
throw e;
} finally {
await queryRunner.release();
category,
userInDb,
);
}

const content = new Content();
content.link = link;
content.title = title;
content.siteName = siteName;
content.coverImg = coverImg;
content.description = description;
content.comment = comment;
content.reminder = reminder;
content.category = category;
content.user = user;
content.favorite = favorite;

await this.contentRepository.createOne(content, entityManager);
return {};
}

@Transactional()
Expand Down Expand Up @@ -163,7 +151,7 @@ export class ContentsService {
description,
user: userInDb,
});
await this.contentRepository.saveOne(newContent, entityManager);
await this.contentRepository.createOne(newContent, entityManager);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/contents/entities/content.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class Content extends CoreEntity {
@ApiProperty({ description: 'Favorite' })
@Column({ default: false })
@IsBoolean()
favorite!: boolean;
favorite?: boolean;

@ApiProperty({ description: 'Article Category', required: false })
@ManyToOne((type) => Category, (category) => category.contents, {
Expand Down
2 changes: 1 addition & 1 deletion src/contents/repository/content.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class ContentRepository extends Repository<Content> {
.getCount();
}

async saveOne(
async createOne(
content: Content,
entityManager?: EntityManager,
): Promise<Content> {
Expand Down
1 change: 1 addition & 0 deletions src/contents/util/content.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const getLinkInfo = async (link: string) => {
link = `http://${link}`;
}

// ! TODO 크롤링에서 대략 초 단위 시간 소요 -> 개선 필요
await axios
.get(link)
.then((res) => {
Expand Down

0 comments on commit 5057317

Please sign in to comment.