From 0133872586be44043a88d702d4e179b220aef0af Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 30 May 2026 04:38:51 +0530 Subject: [PATCH] enrich and save progress with percentage count --- src/FetchRequestDetail.tsx | 56 ++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/FetchRequestDetail.tsx b/src/FetchRequestDetail.tsx index 2dbd83d..0181f54 100644 --- a/src/FetchRequestDetail.tsx +++ b/src/FetchRequestDetail.tsx @@ -62,21 +62,43 @@ function computeProgressPercent( status: FetchRequestStatus, liveCount: number, seenSteps: Set, + stepStats: Record, ): number { if (status === "pending") return 0; if (status === "completed") return 100; - if (seenSteps.has("save_expenses") || seenSteps.has("complete")) return 95; - if (seenSteps.has("enrich")) return 85; - if (seenSteps.has("txn_dicts/completed")) return 80; + const W_EXTRACT = 10; + const W_RAW = 20; + const W_ENRICH = 50; + const W_SAVE = 20; - if (seenSteps.has("txn_dicts") && liveCount > 0) { - return Math.min(80, 20 + Math.min(liveCount, 300) / 300 * 60); + let pct = 0; + + if (seenSteps.has("raw_lines") || seenSteps.has("txn_blocks")) pct += W_EXTRACT; + + const blocks = stepStats.txn_blocks ?? 0; + if (seenSteps.has("txn_dicts/completed") || status === "raw_expenses_done") { + pct += W_RAW; + } else if (blocks > 0 && liveCount > 0) { + pct += Math.min(1, liveCount / blocks) * W_RAW; } - if (seenSteps.has("txn_blocks") || seenSteps.has("raw_lines")) return 20; + const totalDicts = stepStats.txn_dicts ?? 0; + const enrichCount = stepStats.enrich_count ?? 0; + if (seenSteps.has("enrich/completed") || (seenSteps.has("enrich") && totalDicts > 0 && enrichCount >= totalDicts)) { + pct += W_ENRICH; + } else if (totalDicts > 0 && enrichCount > 0) { + pct += Math.min(1, enrichCount / totalDicts) * W_ENRICH; + } - return status === "processing" || status === "paused" ? 5 : 0; + const saveCount = stepStats.save_count ?? 0; + if (seenSteps.has("save_expenses/completed") || seenSteps.has("complete/completed")) { + pct += W_SAVE; + } else if (totalDicts > 0 && saveCount > 0) { + pct += Math.min(1, saveCount / totalDicts) * W_SAVE; + } + + return Math.round(Math.min(100, pct)); } const stepLabels = ["Extract", "Raw Expense", "Enrich", "Save"]; @@ -187,8 +209,10 @@ export default function FetchRequestDetail() { const parsed: SSEEvent = JSON.parse(event.data); setSseEvents((prev) => [...prev, parsed]); - if (parsed.step === "txn_dicts" && parsed.status === "progress" && parsed.message.count !== undefined) { - setLiveParsedCount(parsed.message.count); + if (parsed.status === "progress" && parsed.message.count !== undefined) { + if (parsed.step === "txn_dicts") setLiveParsedCount(parsed.message.count); + if (parsed.step === "enrich") setStepStats((prev) => ({ ...prev, enrich_count: parsed.message.count! })); + if (parsed.step === "save_expenses") setStepStats((prev) => ({ ...prev, save_count: parsed.message.count! })); } if (parsed.status === "completed" && parsed.message.count !== undefined) { @@ -228,17 +252,18 @@ export default function FetchRequestDetail() { }, [sseEvents]); const displayEvents = React.useMemo(() => { - let lastProgressIdx = -1; + const progressSteps = new Set(["txn_dicts", "enrich", "save_expenses"]); + const lastProgressIdx: Record = {}; for (let i = sseEvents.length - 1; i >= 0; i--) { - if (sseEvents[i].step === "txn_dicts" && sseEvents[i].status === "progress") { - lastProgressIdx = i; - break; + const e = sseEvents[i]; + if (progressSteps.has(e.step) && e.status === "progress" && lastProgressIdx[e.step] === undefined) { + lastProgressIdx[e.step] = i; } } const terminalStatuses = new Set(["completed", "skipped", "paused"]); return sseEvents.filter((e, i) => { - if (e.step === "txn_dicts" && e.status === "progress") return i === lastProgressIdx; + if (progressSteps.has(e.step) && e.status === "progress") return i === lastProgressIdx[e.step]; if (e.status === "started") { return !sseEvents.slice(i + 1).some( (later) => later.step === e.step && terminalStatuses.has(later.status), @@ -264,8 +289,9 @@ export default function FetchRequestDetail() { (fetchRequest as any)?.status as FetchRequestStatus ?? "pending", liveParsedCount ?? 0, seenSteps, + stepStats, ), - [fetchRequest, liveParsedCount, seenSteps], + [fetchRequest, liveParsedCount, seenSteps, stepStats], ); const displayParsedCount = React.useMemo(() => {