BLAST database download progress, ETA, and cancel confirmation¶
Motivation¶
The BLAST database modal's per-DB download row (the hardened prepare-db copy flow) had three rough edges the user called out:
- The "Copying X / Y files" counter jumped up and down. The displayed
numerator was
copy_status.success ?? file_count ?? 0. Whenever the server-side copy metadata momentarily lackedcopy_status.success, the UI fell back to the live blob-listingfile_count— a different, larger number that fluctuates while copies are mid-flight — so the count visibly flickered between the two sources. - Cancelling was a one-click action with no confirmation. The Cancel button called the abort endpoint immediately, with no "are you sure" step.
- The estimate was static. The row showed the catalog's fixed
est. ~2-4 hoursregardless of how the copy was actually progressing.
User-facing change¶
- Flicker-free count. The copied-file count now trusts only
copy_status.successduring an active copy (nofile_countfallback) and is clamped to be monotonic non-decreasing within a single copy session, so it only ever increases. - Live ETA. The static
est. <catalog>text is replaced by a dynamic estimate projected from observed throughput (success / elapsed). It showsestimating…until throughput stabilises, then tightens to~7m left/~1h 5m leftas the copy runs. - Cancel confirmation. Clicking Cancel now opens a confirmation dialog
("Cancel download of
? Files already copied stay in place; only the remaining pending copies are aborted.") and only calls the abort endpoint after the user confirms.
Note: the download still uses the server-side copy path (the
apisidecar issues per-filestart_copy_from_urlS3→blob copies). The AKS-nodeazcopyfan-out path exists in the backend (mode=aks/auto) but the dashboard download button does not request it; wiring that mode into the UI is a separate change.
Diff summary¶
web/src/components/cards/storage/blastDbProgress.ts(new) — pureformatDuration/formatEtahelpers projecting remaining time from copied/total + elapsed seconds.web/src/components/cards/storage/blastDbProgress.test.ts(new) — 8 unit tests for the duration/ETA math.web/src/components/cards/storage/BlastDbRow.tsx— monotonic copied-count via auseRefclamp, local copy-% computed from the monotonic count, live ETA label; dropped thefile_countfallback and the staticdb.estMinutesfrom the copying line; removed thecopyProgressprop (now computed locally).web/src/components/cards/storage/BlastDbModal.tsx— removed the flicker-pronecopyProgresscomputation; added aconfirmCancelDbstate and aConfirmDialoggate so Cancel requires confirmation;onCancelnow opens the dialog instead of aborting directly.
No backend/IaC changes.
Validation evidence¶
npx vitest run src/components/cards/storage/blastDbProgress.test.ts src/utils/blastDbReady.test.ts→ 18 passed.npx vitest run src/components/cards/storage→ 19 passed (4 files).npm run build→ clean (tsc + vite, built in ~6 s).