Skip to content

feat(cli): loading indicators for indexes list and usage - #215

Merged
eddietejeda merged 5 commits into
mainfrom
feat/loading-indicators
Jul 10, 2026
Merged

eddietejeda merged 5 commits into
mainfrom
feat/loading-indicators

Conversation

@eddietejeda

Copy link
Copy Markdown
Contributor

Both commands sat silent while fetching:

  • indexes list: one spinner over the whole fetch — the unscoped path is a whole-workspace scan (connections enumeration + managed-DB discovery + per-table index reads) that can take seconds. The database discovery inside the scan (databases::list_database_ids) becomes deliberately spinner-less so its nested "Loading databases…" bar never fights the outer one for the line; databases list itself keeps the wakeup-hint spinner.
  • usage: plain spinner around its single request, cleared before rendering or error exit.

Smoke-tested both against prod.

Both commands sat silent while fetching. `indexes list` gets one spinner
over the whole fetch - the unscoped path is a whole-workspace scan
(connections enumeration + managed-DB discovery + per-table index reads)
that can take seconds. The database discovery inside the scan
(databases::list_database_ids) drops its nested "Loading databases..."
wakeup spinner so two indicatif bars never fight over the same line;
`databases list` itself keeps the wakeup-hint spinner. `usage` gets a
plain spinner around its single request.
Comment thread src/commands/indexes.rs
// whole-workspace scan (many requests) that otherwise sits silent.
// The database discovery inside is deliberately spinner-less
// (databases::list_database_ids) so nothing fights for the line.
let spinner = crate::util::spinner("Loading indexes…");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This spinner is only cleared at line 525, after the match block — so it is never cleared on the error path. Every fetch inside the match (list_one_table, collect_connection_wide, and list_database_ids) exits via e.exit() on API error, which calls ApiError::print() (writes directly to stderr with eprintln!) and then process::exit(1). When that happens, the steady-ticking spinner is still active: the error message gets written over/interleaved with the spinner line, and the spinner is left stuck on the terminal after exit.

This is exactly the "two bars fight over the same line" problem you deliberately avoided — and in usage.rs you handled the equivalent case correctly by capturing the Result and clearing the spinner before e.exit():

let result = api.get_json("/usage", &query);
spinner.finish_and_clear();
let u: Usage = result.unwrap_or_else(|e| e.exit());

The indexes path needs the same treatment, but the exits happen deep inside the helper functions, so finish_and_clear() after the match doesn't cover them. Consider having the fetch helpers return Result so the caller can clear the spinner before exiting, or otherwise ensure the spinner is finished before any error is printed.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — Blocking

Blocking Issues

  • src/commands/indexes.rs:507 — the "Loading indexes…" spinner is only cleared after the match block (line 525), so it is never cleared on the error path. All three fetch helpers exit via e.exit() on API error, which prints to stderr and process::exit(1)s while the steady-ticking spinner is still active. This interleaves the error message with the spinner and leaves the spinner stuck on the terminal — the same line-fight you correctly avoided in usage.rs.

Action Required
Ensure the spinner is finished before any error is printed on the indexes path. Since the exits happen inside the fetch helpers, cleaning up after the match is not sufficient — have the helpers return Result so the caller can finish_and_clear() before e.exit() (mirroring the usage.rs pattern).

@codecov

codecov Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.76768% with 23 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/commands/databases.rs 25.00% 12 Missing ⚠️
src/commands/indexes.rs 94.73% 4 Missing ⚠️
src/commands/usage.rs 0.00% 4 Missing ⚠️
src/commands/ingest.rs 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

eddietejeda and others added 4 commits July 9, 2026 19:55
* feat(databases): show created_at in list and show commands

Adds a CREATED column to `databases list` and a created_at row to
`databases show`. Uses the updated SDK models from sdk-rust
feat/database-timestamps (PR #909 in runtimedb).

Cargo.toml temporarily points to local sdk-rust path; update to
published version once sdk-rust feat/database-timestamps is released.

* chore: update hotdata SDK to v0.8.1 (created_at on databases)

---------

Co-authored-by: Eddie A Tejeda <669988+eddietejeda@users.noreply.github.com>
'hotdata ingest datasources' now browses the catalog of available
datasource types; 'connectors' stays as a hidden alias. Help, error
hints, README, and the skill follow.

Co-authored-by: Eddie A Tejeda <669988+eddietejeda@users.noreply.github.com>
The fetch helpers called e.exit() (process::exit) internally, leaving
the indicatif spinner live on the terminal when any API call failed.
Convert list_one_table, list_one_table_scan, collect_tables,
connection_lookup, managed_db_connection_ids, workspace_scan_targets,
and collect_connection_wide to return Result<_, ApiError>, then
finish_and_clear() the spinner in list() before unwrap_or_else(|e|
e.exit()) -- matching the usage.rs pattern.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cycle 2: prior blocking issue (spinner left live on the error path in indexes.rs) is resolved. The fetch helpers now return Result, and list() clears the spinner before unwrap_or_else(|e| e.exit()) — matching the usage.rs pattern. No new issues.

@eddietejeda
eddietejeda merged commit 5fc3b07 into main Jul 10, 2026
14 checks passed
@eddietejeda
eddietejeda deleted the feat/loading-indicators branch July 10, 2026 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant