Context
The migration path in vireo/db.py:_create_tables runs at app startup. After #636, this includes — for users upgrading from an older schema — two table rewrites: detections (drop workspace_id, dedupe across workspaces) and predictions (rename model → classifier_model, add labels_fingerprint, drop review columns). On large libraries, the predictions rewrite reads every prediction row.
Today this is silent: the user sees a hung Flask startup / browser-loading state with no indication of progress. The first run after upgrade is also the slowest.
Fix
Two parts:
- Server-side: structured log lines around each long-running migration block — name, start/finish timestamps, row counts. Some logging exists; the structured form is missing.
- Client-side: an "Upgrading database…" splash on first run after upgrade, driven by a startup-status flag. Could reuse the existing job SSE infrastructure, or a simpler
GET /api/startup/status poll. Block normal UI loads behind it.
Acceptance
A user upgrading a library with ~100k predictions sees a clearly-labeled progress UI instead of a hung tab. The splash names the current step (e.g. "Migrating predictions table — 47k of 100k").
Scope guard
Only the cold-boot upgrade path. Subsequent runs of _create_tables (no-op for already-migrated DBs) should not trigger the splash.
Context
The migration path in
vireo/db.py:_create_tablesruns at app startup. After #636, this includes — for users upgrading from an older schema — two table rewrites:detections(dropworkspace_id, dedupe across workspaces) andpredictions(renamemodel→classifier_model, addlabels_fingerprint, drop review columns). On large libraries, the predictions rewrite reads every prediction row.Today this is silent: the user sees a hung Flask startup / browser-loading state with no indication of progress. The first run after upgrade is also the slowest.
Fix
Two parts:
GET /api/startup/statuspoll. Block normal UI loads behind it.Acceptance
A user upgrading a library with ~100k predictions sees a clearly-labeled progress UI instead of a hung tab. The splash names the current step (e.g. "Migrating predictions table — 47k of 100k").
Scope guard
Only the cold-boot upgrade path. Subsequent runs of
_create_tables(no-op for already-migrated DBs) should not trigger the splash.