From 9d00afc23fca94056ce630dfdd91e16010cad7aa Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Thu, 6 Nov 2025 15:06:21 +0900 Subject: (김준회) PQ 및 실사 캐싱 제거 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pq/service.ts | 43 +++++----- lib/vendor-investigation/service.ts | 164 +++++++++++++++++------------------- 2 files changed, 101 insertions(+), 106 deletions(-) (limited to 'lib') diff --git a/lib/pq/service.ts b/lib/pq/service.ts index bc3f37a0..15d9aebc 100644 --- a/lib/pq/service.ts +++ b/lib/pq/service.ts @@ -1451,6 +1451,8 @@ export interface VendorPQsList { } export async function getVendorPQsList(vendorId: number): Promise { + unstable_noStore(); + try { // 1. Check if vendor has general PQ answers const generalPqAnswers = await db @@ -1539,6 +1541,8 @@ export async function loadProjectPQAction(vendorId: number, projectId?: number): export async function getAllPQsByVendorId(vendorId: number) { + unstable_noStore(); + try { const pqList = await db .select({ @@ -1569,6 +1573,8 @@ export async function getAllPQsByVendorId(vendorId: number) { // 특정 PQ의 상세 정보 조회 (개별 PQ 페이지용) export async function getPQById(pqSubmissionId: number, vendorId: number) { + unstable_noStore(); + try { const pq = await db @@ -1679,8 +1685,8 @@ function getStatusLabel(status: string): string { } export async function getPQSubmissions(input: GetPQSubmissionsSchema) { - return unstable_cache( - async () => { + unstable_noStore(); + try { const offset = (input.page - 1) * input.perPage; @@ -1989,16 +1995,11 @@ export async function getPQSubmissions(input: GetPQSubmissionsSchema) { console.error("Error in getPQSubmissions:", err); return { data: [], pageCount: 0 }; } - }, - [JSON.stringify(input)], // 캐싱 키 - { - revalidate: 3600, - tags: ["pq-submissions"], // revalidateTag 호출 시 무효화 - } - )(); } export async function getPQStatusCountsAll() { + unstable_noStore(); + try { // 모든 PQ 상태별 개수 조회 (벤더 제한 없음) const pqStatuses = await db @@ -3046,8 +3047,12 @@ export async function requestInvestigationAction( // 이메일 발송 실패는 로그만 남기고 전체 프로세스는 성공으로 처리 console.error("이메일 발송 중 오류 발생:", emailErr); } - revalidatePath("/evcp/pq_new"); - revalidatePath("/evcp/vendor-investigation"); + + // 캐시 무효화 (skipRevalidation 옵션이 false일 때만) + if (!options?.skipRevalidation) { + revalidateTag("vendor-investigations") + revalidateTag("pq-submissions") + } return { success: true, @@ -3092,11 +3097,9 @@ export async function cancelInvestigationAction(investigationIds: number[]) { return updatedInvestigations }) - // 캐시 무효화 (핸들러에서 호출 시에는 건너뛰기) - if (!options?.skipRevalidation) { - revalidateTag("vendor-investigations") - revalidateTag("pq-submissions") - } + // 캐시 무효화 + revalidateTag("vendor-investigations") + revalidateTag("pq-submissions") return { success: true, @@ -3160,9 +3163,11 @@ export async function reRequestInvestigationAction( return updatedInvestigations }) - // 캐시 무효화 - revalidateTag("vendor-investigations") - revalidateTag("pq-submissions") + // 캐시 무효화 (skipRevalidation 옵션이 false일 때만) + if (!options?.skipRevalidation) { + revalidateTag("vendor-investigations") + revalidateTag("pq-submissions") + } return { success: true, diff --git a/lib/vendor-investigation/service.ts b/lib/vendor-investigation/service.ts index c365a7ad..39984661 100644 --- a/lib/vendor-investigation/service.ts +++ b/lib/vendor-investigation/service.ts @@ -20,94 +20,84 @@ import { decryptWithServerAction } from "@/components/drm/drmUtils"; import { format, addDays } from "date-fns"; export async function getVendorsInvestigation(input: GetVendorsInvestigationSchema) { - return unstable_cache( - async () => { - try { - const offset = (input.page - 1) * input.perPage - - // 1) Advanced filters - const advancedWhere = filterColumns({ - table: vendorInvestigationsView, - filters: input.filters, - joinOperator: input.joinOperator, - }) - - // 2) Global search - let globalWhere - if (input.search) { - const s = `%${input.search}%` - globalWhere = or( - // 협력업체 정보 - ilike(vendorInvestigationsView.vendorName, s), - ilike(vendorInvestigationsView.vendorCode, s), - - // 담당자 정보 (새로 추가) - ilike(vendorInvestigationsView.requesterName, s), - ilike(vendorInvestigationsView.qmManagerName, s), - - // 실사 정보 - ilike(vendorInvestigationsView.investigationNotes, s), - ilike(vendorInvestigationsView.investigationStatus, s), - ilike(vendorInvestigationsView.investigationAddress, s), - ilike(vendorInvestigationsView.investigationMethod, s), - - // 평가 결과 - ilike(vendorInvestigationsView.evaluationResult, s) - ) - } - // 3) Combine finalWhere - const finalWhere = and( - advancedWhere, - globalWhere - ) - - // 4) Sorting - const orderBy = - input.sort && input.sort.length > 0 - ? input.sort.map((item) => - item.desc - ? desc(vendorInvestigationsView[item.id]) - : asc(vendorInvestigationsView[item.id]) - ) - : [desc(vendorInvestigationsView.createdAt)] - - // 5) Query & count - const { data, total } = await db.transaction(async (tx) => { - // a) Select from the view - const investigationsData = await tx - .select() - .from(vendorInvestigationsView) - .where(finalWhere) - .orderBy(...orderBy) - .offset(offset) - .limit(input.perPage) - - // b) Count total - const resCount = await tx - .select({ count: count() }) - .from(vendorInvestigationsView) - .where(finalWhere) - - return { data: investigationsData, total: resCount[0]?.count } - }) - - // 6) Calculate pageCount - const pageCount = Math.ceil(total / input.perPage) - - // Data is already in the correct format from the simplified view - return { data, pageCount } - } catch (err) { - console.error(err) - return { data: [], pageCount: 0 } - } - }, - // Cache key - [JSON.stringify(input)], - { - revalidate: 3600, - tags: ["vendor-investigations"], + try { + const offset = (input.page - 1) * input.perPage + + // 1) Advanced filters + const advancedWhere = filterColumns({ + table: vendorInvestigationsView, + filters: input.filters, + joinOperator: input.joinOperator, + }) + + // 2) Global search + let globalWhere + if (input.search) { + const s = `%${input.search}%` + globalWhere = or( + // 협력업체 정보 + ilike(vendorInvestigationsView.vendorName, s), + ilike(vendorInvestigationsView.vendorCode, s), + + // 담당자 정보 (새로 추가) + ilike(vendorInvestigationsView.requesterName, s), + ilike(vendorInvestigationsView.qmManagerName, s), + + // 실사 정보 + ilike(vendorInvestigationsView.investigationNotes, s), + ilike(vendorInvestigationsView.investigationStatus, s), + ilike(vendorInvestigationsView.investigationAddress, s), + ilike(vendorInvestigationsView.investigationMethod, s), + + // 평가 결과 + ilike(vendorInvestigationsView.evaluationResult, s) + ) } - )() + // 3) Combine finalWhere + const finalWhere = and( + advancedWhere, + globalWhere + ) + + // 4) Sorting + const orderBy = + input.sort && input.sort.length > 0 + ? input.sort.map((item) => + item.desc + ? desc(vendorInvestigationsView[item.id]) + : asc(vendorInvestigationsView[item.id]) + ) + : [desc(vendorInvestigationsView.createdAt)] + + // 5) Query & count + const { data, total } = await db.transaction(async (tx) => { + // a) Select from the view + const investigationsData = await tx + .select() + .from(vendorInvestigationsView) + .where(finalWhere) + .orderBy(...orderBy) + .offset(offset) + .limit(input.perPage) + + // b) Count total + const resCount = await tx + .select({ count: count() }) + .from(vendorInvestigationsView) + .where(finalWhere) + + return { data: investigationsData, total: resCount[0]?.count } + }) + + // 6) Calculate pageCount + const pageCount = Math.ceil(total / input.perPage) + + // Data is already in the correct format from the simplified view + return { data, pageCount } + } catch (err) { + console.error(err) + return { data: [], pageCount: 0 } + } } /** * Get existing investigations for a list of vendor IDs -- cgit v1.2.3