BLAST DB: clear stale "Update available" after a successful update¶
Motivation¶
After a successful DB update (e.g. 16S_ribosomal_RNA promoted by the AKS
fan-out path), the BLAST Databases card still showed an orange Update
button on that database and kept counting it in the "N updates available"
badge. The database looked un-updated even though the backend had correctly
promoted the new generation.
Root cause (two bugs)¶
-
Stale
check-updatesquery. The SPA's per-DB update list comes fromGET /api/blast/databases/check-updates, cached under theblast-db-latest-versionReact Query key withstaleTime: 300_000and norefetchIntervaland no invalidation when a copy/update completes. So after a promote, the SPA kept serving the pre-update list — which still contained the database the user had just refreshed — for minutes. -
Rotate-sensitive legacy fallback. When the server returned an empty
updates_availablelist, the SPA could not tell "evaluated, nothing stale" from "not evaluated (no storage scope)". It fell back to the coarsesource_version !== latest_versionheuristic, which re-flags every database whenever NCBI rotates itslatest-dirtag — even when the underlying database content is unchanged. This produced false "Update available" badges once all real updates had been applied.
Ground truth from the deployed check-updates (per-DB signature comparison):
16S_ribosomal_RNA was correctly absent from the list after its update,
while 18S_fungal_sequences, ITS_RefSeq_Fungi, and core_nt had genuinely
different composite signatures (real content change, not just a latest-dir
rotation).
User-facing change¶
- The Update button and the "N updates available" badge clear immediately after a database update finishes, instead of lingering for minutes.
- Databases whose NCBI
latest-dirmerely rotated (no content change) no longer show a false "Update available" once all genuine updates are applied. - No change to which databases genuinely need an update — the authoritative per-DB NCBI signature comparison is unchanged.
API / IaC diff summary¶
api/routes/blast/databases.py—check-updatesresponse gains an additive booleanupdates_available_evaluated(defaultfalse;trueonly after the per-DB signature comparison actually runs). No IaC change.web/src/api/blast.ts—checkUpdatesresponse type adds the optionalupdates_available_evaluatedand the already-returnedcomposite_signature/stored_composite_signatureitem fields.web/src/components/cards/storage/useBlastDb.ts—- the "updates available" count gates the legacy fallback on
updates_available_evaluatedinstead of "server list is empty"; - a new effect re-runs the
check-updatesquery on theserverCopyActivefalling edge (any copy/update completion) so the stale badge clears at once; - exposes
updatesEvaluated. web/src/components/cards/storage/blastDbUpdates.ts— new puredbHasUpdatehelper centralising the per-row decision.web/src/components/cards/storage/BlastDbModal.tsx— per-row Update button usesdbHasUpdate(gates the legacy fallback onupdatesEvaluated).
Validation evidence¶
- Backend:
uv run pytest -q api/tests/test_blast_databases_check_updates.py→ 6 passed (newupdates_available_evaluatedassertions:Truewhen the per-DB comparison ran,Falsefor the no-storage-scope legacy shape). Related sweeptest_blast_databases_preview.py+test_prepare_db_aks_task.py→ 24 passed. - Frontend: new
blastDbUpdates.test.ts(7 tests) covers the regression (evaluated + absent from map ⇒ no Update even whenlatest-dirrotated) and the legacy fallback. Storage-card suite → 51 passed.npm run buildclean. - Ground truth: deployed
check-updateswith storage scope returns16S_ribosomal_RNAabsent and the other three present, matching the new SPA behaviour.