diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-05 19:28:49 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-05 19:28:49 +0900 |
| commit | e890fbae0c9c273b825ac808aa516de1f87fb218 (patch) | |
| tree | c2b7bdacd22043a8b4781e9b4c6ea682468abd0f /lib/approval-log/service.ts | |
| parent | 35e373fe29a4145d0692ee35ff9e6b0c887df0eb (diff) | |
(김준회) 실사의뢰 결재 오류 수정, 결재 캐시 백그라운드 컨텍스트에서 패스로 무효화 처리, pm2 ecosystem 설정 변경 (npm 레이어 로그 문제), git 줄바꿈 문제 2건 커밋으로 처리
Diffstat (limited to 'lib/approval-log/service.ts')
| -rw-r--r-- | lib/approval-log/service.ts | 160 |
1 files changed, 91 insertions, 69 deletions
diff --git a/lib/approval-log/service.ts b/lib/approval-log/service.ts index 5690e0f9..64ae40a2 100644 --- a/lib/approval-log/service.ts +++ b/lib/approval-log/service.ts @@ -10,6 +10,7 @@ import { or, sql, } from 'drizzle-orm'; +import { unstable_cache } from 'next/cache'; import db from '@/db/db'; import { approvalLogs } from '@/db/schema/knox/approvals'; @@ -39,85 +40,106 @@ interface ListInput { sort?: Array<{ id: string; desc: boolean }>; } +/** + * 결재 로그 목록 조회 (캐시 적용) + * + * 캐시 태그: 'approval-logs' + * 캐시 무효화: /api/revalidate/approval 호출 시 + */ export async function getApprovalLogList(input: ListInput) { - const offset = (input.page - 1) * input.perPage; + // 캐시 키 생성 (검색/필터/정렬 조건 포함) + const cacheKey = `approval-logs-${JSON.stringify(input)}`; + + return unstable_cache( + async () => { + const offset = (input.page - 1) * input.perPage; - /* ------------------------------------------------------------------ - * WHERE 절 구성 - * ----------------------------------------------------------------*/ - const advancedWhere = filterColumns({ - table: approvalLogs, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - filters: (input.filters ?? []) as any, - joinOperator: (input.joinOperator ?? 'and') as 'and' | 'or', - }); + /* ------------------------------------------------------------------ + * WHERE 절 구성 + * ----------------------------------------------------------------*/ + const advancedWhere = filterColumns({ + table: approvalLogs, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + filters: (input.filters ?? []) as any, + joinOperator: (input.joinOperator ?? 'and') as 'and' | 'or', + }); - // 전역 검색 (subject, content, emailAddress, userId) - let globalWhere; - if (input.search) { - const s = `%${input.search}%`; - globalWhere = or( - ilike(approvalLogs.subject, s), - ilike(approvalLogs.content, s), - ilike(approvalLogs.emailAddress, s), - ilike(approvalLogs.userId, s), - ); - } + // 전역 검색 (subject, content, emailAddress, userId) + let globalWhere; + if (input.search) { + const s = `%${input.search}%`; + globalWhere = or( + ilike(approvalLogs.subject, s), + ilike(approvalLogs.content, s), + ilike(approvalLogs.emailAddress, s), + ilike(approvalLogs.userId, s), + ); + } - let where = eq(approvalLogs.isDeleted, false); // 기본적으로 삭제되지 않은 것만 조회 + let where = eq(approvalLogs.isDeleted, false); // 기본적으로 삭제되지 않은 것만 조회 - if (advancedWhere && globalWhere) { - where = and(where, advancedWhere, globalWhere); - } else if (advancedWhere) { - where = and(where, advancedWhere); - } else if (globalWhere) { - where = and(where, globalWhere); - } + if (advancedWhere && globalWhere) { + const combined = and(where, advancedWhere, globalWhere); + if (combined) where = combined; + } else if (advancedWhere) { + const combined = and(where, advancedWhere); + if (combined) where = combined; + } else if (globalWhere) { + const combined = and(where, globalWhere); + if (combined) where = combined; + } - /* ------------------------------------------------------------------ - * ORDER BY 절 구성 - * ----------------------------------------------------------------*/ - let orderBy; - try { - orderBy = input.sort && input.sort.length > 0 - ? input.sort - .map((item) => { - if (!item || !item.id || typeof item.id !== 'string') return null; - if (!(item.id in approvalLogs)) return null; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const col = approvalLogs[item.id]; - return item.desc ? desc(col) : asc(col); - }) - .filter((v): v is Exclude<typeof v, null> => v !== null) - : [desc(approvalLogs.createdAt)]; - } catch { - orderBy = [desc(approvalLogs.createdAt)]; - } + /* ------------------------------------------------------------------ + * ORDER BY 절 구성 + * ----------------------------------------------------------------*/ + let orderBy; + try { + orderBy = input.sort && input.sort.length > 0 + ? input.sort + .map((item) => { + if (!item || !item.id || typeof item.id !== 'string') return null; + if (!(item.id in approvalLogs)) return null; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const col = approvalLogs[item.id]; + return item.desc ? desc(col) : asc(col); + }) + .filter((v): v is Exclude<typeof v, null> => v !== null) + : [desc(approvalLogs.createdAt)]; + } catch { + orderBy = [desc(approvalLogs.createdAt)]; + } - /* ------------------------------------------------------------------ - * 데이터 조회 - * ----------------------------------------------------------------*/ - const data = await db - .select() - .from(approvalLogs) - .where(where) - .orderBy(...orderBy) - .limit(input.perPage) - .offset(offset); + /* ------------------------------------------------------------------ + * 데이터 조회 + * ----------------------------------------------------------------*/ + const data = await db + .select() + .from(approvalLogs) + .where(where) + .orderBy(...orderBy) + .limit(input.perPage) + .offset(offset); - const totalResult = await db - .select({ count: count() }) - .from(approvalLogs) - .where(where); + const totalResult = await db + .select({ count: count() }) + .from(approvalLogs) + .where(where); - const total = totalResult[0]?.count ?? 0; - const pageCount = Math.ceil(total / input.perPage); + const total = totalResult[0]?.count ?? 0; + const pageCount = Math.ceil(total / input.perPage); - return { - data, - pageCount, - }; + return { + data, + pageCount, + }; + }, + [cacheKey], + { + tags: ['approval-logs'], // 캐시 태그 + revalidate: 60, // 60초마다 자동 재검증 (폴백) + } + )(); } // ---------------------------------------------------- |
