Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 30 additions & 43 deletions src/services/getProfileFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const getBook = new GetBook({ accessToken: SSC_TOKEN });
* @returns {Promise<import('@frolog/frolog-api').GetProfileFeedRes>} 응답 DTO.
*/
export default async function getProfileFeed(reqDto, user) {
// (1) 유저 ID 디코드
// (1) 유저 ID 디코드 및 권한 검사
if (!user.is_admin && user.id !== reqDto.id) {
// 권한 없음
throw new FetchError('Unauthorized request.', 403);
Expand All @@ -37,18 +37,15 @@ export default async function getProfileFeed(reqDto, user) {
const page = reqDto.page ?? 0;
const offset = page * limit;

// (3) 메모와 리뷰 조회
// (3) 메모와 리뷰 집계 조회
const [memoCounts, reviewCounts] = await Promise.all([
Memo.findAll({
attributes: [
'book_isbn',
[fn('COUNT', col('memo_id')), 'memo_count'],
[fn('MAX', col('updated_at')), 'last_updated'],
],
where: {
writer_id: userId,
deleted_at: null,
},
where: { writer_id: userId, deleted_at: null },
group: ['book_isbn'],
raw: true,
}).catch(handleSqlError),
Expand All @@ -58,15 +55,13 @@ export default async function getProfileFeed(reqDto, user) {
[fn('COUNT', col('review_id')), 'review_count'],
[fn('MAX', col('updated_at')), 'last_updated'],
],
where: {
writer_id: userId,
deleted_at: null,
},
where: { writer_id: userId, deleted_at: null },
group: ['book_isbn'],
raw: true,
}).catch(handleSqlError),
]);

// (4) ISBN 별 메모/리뷰 정보 병합
const contentMap = new Map();
/* eslint-disable camelcase */
memoCounts.forEach(({ book_isbn, memo_count, last_updated }) => {
Expand All @@ -76,7 +71,6 @@ export default async function getProfileFeed(reqDto, user) {
lastUpdated: last_updated,
});
});

reviewCounts.forEach(({ book_isbn, review_count, last_updated }) => {
if (!contentMap.has(book_isbn)) {
contentMap.set(book_isbn, {
Expand All @@ -94,43 +88,36 @@ export default async function getProfileFeed(reqDto, user) {
});
/* eslint-enable camelcase */

// (5) 페이지네이션 적용
// (5) 최신 활동 기준 정렬 및 페이지네이션 적용
const entries = Array.from(contentMap.entries())
.sort((a, b) => {
// 최신 활동 시간 기준으로 정렬
return new Date(b[1].lastUpdated) - new Date(a[1].lastUpdated);
})
.sort((a, b) => new Date(b[1].lastUpdated) - new Date(a[1].lastUpdated))
.slice(offset, offset + limit);

// (6) 도서 정보와 우물 정보 조회
const items = await Promise.all(
entries.map(async ([isbn, counts]) => {
// (1) 도서 정보 조회
const bookInfo = await getBook.fetch({ isbn });
// (6) 도서 정보 및 우물 정보 조회
const items = [];
for (const [isbn, counts] of entries) {
// (6.1) 도서 정보 조회 (실패 시 null 반환)
let bookInfo = null;
try {
bookInfo = await getBook.fetch({ isbn });
} catch (err) {
// 도서 정보 조회 실패 시 해당 항목은 건너뜀
continue;
}

// (2) 우물 정보 조회
const well = await Well.findOne({
include: [
{
model: WellItem,
where: {
book_isbn: isbn,
},
},
],
where: {
owner_id: userId,
},
}).catch(handleSqlError);
// (6.2) 우물 정보 조회
const well = await Well.findOne({
include: [{ model: WellItem, where: { book_isbn: isbn } }],
where: { owner_id: userId },
}).catch(handleSqlError);

return {
memoCount: counts.memoCount,
reviewCount: counts.reviewCount,
book: bookInfo,
wellId: well ? encodeHashId(well.well_id) : undefined,
};
}),
);
items.push({
memoCount: counts.memoCount,
reviewCount: counts.reviewCount,
book: bookInfo,
wellId: well ? encodeHashId(well.well_id) : undefined,
});
}

// (7) 데이터 반환
return {
Expand Down
Loading