From f49f99fc0cafe3aea9260ae01f4aa6a89d70d0df Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Fri, 17 Apr 2026 12:42:07 +0800 Subject: [PATCH] perf(cleaner-history): parallelize batch fetching in searchBatches Replace sequential for-loop with Promise.all so that matched batches are fetched concurrently instead of one-by-one, reducing total query latency from O(n) serial round-trips to a single parallel batch. Co-Authored-By: Claude Opus 4.6 --- .../database/cleaner-operation-history-dao.ts | 103 +++++++++--------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/src/main/services/database/cleaner-operation-history-dao.ts b/src/main/services/database/cleaner-operation-history-dao.ts index e2f4ca7..43d0006 100644 --- a/src/main/services/database/cleaner-operation-history-dao.ts +++ b/src/main/services/database/cleaner-operation-history-dao.ts @@ -1068,63 +1068,66 @@ export class CleanerOperationHistoryDAO { return { batches: [], totalMatches: 0 } } - // Fetch full nested data for each matched batch - const batches: CleanerSearchBatchResult[] = [] + // Fetch full nested data for each matched batch (parallel) + const batchResults = await Promise.all( + limitedBatchIds.map(async (batchId) => { + try { + const details = await this.getBatchDetails(batchId) - for (const batchId of limitedBatchIds) { - try { - const details = await this.getBatchDetails(batchId) + if (details.executions.length === 0) { + return null + } - if (details.executions.length === 0) { - continue - } + // Derive batch stats from execution records + const latestExec = details.executions.reduce((a, b) => + a.attemptNumber > b.attemptNumber ? a : b + ) - // Derive batch stats from execution records - const latestExec = details.executions.reduce((a, b) => - a.attemptNumber > b.attemptNumber ? a : b - ) + const batch: CleanerBatchStats = { + batchId, + userId: latestExec.userId, + username: latestExec.username, + operationTime: latestExec.operationTime.toISOString(), + status: latestExec.status, + totalAttempts: details.executions.length, + totalOrders: latestExec.totalOrders, + ordersProcessed: latestExec.ordersProcessed, + totalMaterialsDeleted: latestExec.totalMaterialsDeleted, + totalMaterialsFailed: latestExec.totalMaterialsFailed, + successCount: details.orders.filter((o) => o.status === 'success').length, + failedCount: details.orders.filter((o) => o.status === 'failed').length, + isDryRun: latestExec.isDryRun + } - const batch: CleanerBatchStats = { - batchId, - userId: latestExec.userId, - username: latestExec.username, - operationTime: latestExec.operationTime.toISOString(), - status: latestExec.status, - totalAttempts: details.executions.length, - totalOrders: latestExec.totalOrders, - ordersProcessed: latestExec.ordersProcessed, - totalMaterialsDeleted: latestExec.totalMaterialsDeleted, - totalMaterialsFailed: latestExec.totalMaterialsFailed, - successCount: details.orders.filter((o) => o.status === 'success').length, - failedCount: details.orders.filter((o) => o.status === 'failed').length, - isDryRun: latestExec.isDryRun - } + // Fetch materials for each order + const ordersWithMaterials = await Promise.all( + details.orders.map(async (order) => { + const materials = await this.getMaterialDetails( + batchId, + order.attemptNumber, + order.orderNumber + ) + return { order, materials } + }) + ) - // Fetch materials for each order - const ordersWithMaterials = await Promise.all( - details.orders.map(async (order) => { - const materials = await this.getMaterialDetails( - batchId, - order.attemptNumber, - order.orderNumber - ) - return { order, materials } + return { + batch, + executions: details.executions, + orders: ordersWithMaterials + } satisfies CleanerSearchBatchResult + } catch (error) { + log.error('Error fetching batch data for search result', { + operationType: 'SELECT', + batchId, + error: error instanceof Error ? error.message : String(error) }) - ) + return null + } + }) + ) - batches.push({ - batch, - executions: details.executions, - orders: ordersWithMaterials - }) - } catch (error) { - log.error('Error fetching batch data for search result', { - operationType: 'SELECT', - batchId, - error: error instanceof Error ? error.message : String(error) - }) - } - } + const batches = batchResults.filter((r): r is CleanerSearchBatchResult => r !== null) log.info('Search batches completed', { operationType: 'SELECT',