Skip to content

AIR CLI Integration: fast air list via active run index #5814

Merged
riddhibhagwat-db merged 2 commits into
air-clifrom
air-list-fast
Jul 7, 2026
Merged

AIR CLI Integration: fast air list via active run index #5814
riddhibhagwat-db merged 2 commits into
air-clifrom
air-list-fast

Conversation

@riddhibhagwat-db

Copy link
Copy Markdown

Changes

  1. Default to active-only; add --all-status (replaces --active). Plain air list previously scanned every run of every state through Jobs runs/list. It now lists only active runs by default; --all-status opts into all states.

  2. AiTrainingService index fast path for --all-status scoped to yourself. Instead of scanning the Jobs firehose, it fetches cheap (job_run_id, submit_time) pairs from GET /api/2.0/ai-training/workflows, orders by submit time, keeps the newest --limit, and surfaces only those via concurrent Jobs runs/get. If the index is unavailable, it silently falls back to the Jobs scan so the command never hard-fails. --all-users and other-user filters always use the scan (the index is per-user only).

  3. Terminal runs are immutable, so once hydrated, their row is cached; repeat --all-status calls skip runs/get + get-output + MLflow for those ids.

The runFetcher now wraps a listStrategy (jobsScanStrategy | indexStrategy) behind the same next(want)/exhausted contract, so the interactive table, JSON, and one-shot output paths are unchanged.

This PR also fixes a pre-existing recvcheck lint failure and a latent stale-loading guard bug in list_tui.go (fetch helpers converted to value receivers). The index path over-fetches (skips the newest-N truncation) when a --filter on task fields is active, so a filtered-out run can't shrink the result below --limit.

Why

air list in the Go CLI was noticeably slower than the Python AIR CLI — in both plain and --limit modes. The Python CLI's speed comes from three architectural choices, not a faster scan; this PR ports all three to reach parity.

Testing

  • Unit tests: index ordering/limit, 403/404-drop vs 500-propagate, parseSubmitTimeMs, cache-hit-skips-network, gate routing, silent fallback, filter over-fetch.
  • Acceptance: --all-status end-to-end (index → runs/get → get-output) renders fully populated columns.
  • gofmt, lint-q (0 issues), full air acceptance suite green.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: cb3b2f8

Run: 28823663463

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 4 4 267 1025 5:33
💚​ aws windows 4 4 269 1023 6:13
💚​ aws-ucws linux 4 4 363 939 6:12
💚​ aws-ucws windows 4 4 365 937 6:46
💚​ azure linux 4 4 264 1025 5:59
💚​ azure windows 4 4 266 1023 5:28
💚​ azure-ucws linux 4 4 362 937 7:32
💚​ azure-ucws windows 4 4 364 935 6:35
💚​ gcp linux 4 4 260 1028 5:27
💚​ gcp windows 4 4 262 1026 6:54
8 interesting tests: 4 RECOVERED, 4 SKIP
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestFetchRepositoryInfoAPI_FromRepo 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/root 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/subdir 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 20 slowest tests (at least 2 minutes):
duration env testname
5:39 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
5:07 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:35 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:31 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:30 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:27 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:26 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:24 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:01 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:58 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:30 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:20 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:16 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:14 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:01 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:00 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:56 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:45 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:38 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:34 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

Base automatically changed from air-list-pagination to air-cli July 6, 2026 17:07

@vinchenzo-db vinchenzo-db left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

generally lgtm, make sure u understand how are list works because it's a little non-trivial now.

if err != nil || id == 0 {
continue
}
refs = append(refs, workflowRef{jobRunID: id, submitTimeMs: parseSubmitTimeMs(wf.SubmitTime)})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Please make sure you de-duplicate job_run_ids... wouldn't want list to return 20 runs, but 2 are duplicates so user only gets 19.

…nal-run cache

Ports the Python AIR CLI's fast `air list`. Three changes, matching Python:

- Default to active-only; add `--all-status` (replaces `--active`). Plain
  `air list` no longer scans every run of every state, which was the main
  reason it lagged the Python CLI.

- For `--all-status` scoped to yourself, fetch cheap (job_run_id, submit_time)
  pairs from the AiTrainingService index (/api/2.0/ai-training/workflows),
  order by submit time, keep the newest --limit, and hydrate only those via
  Jobs runs/get (concurrent, per-run ACL-enforced: 403/404 drops the id, other
  errors propagate). If the index is unavailable, silently fall back to the
  Jobs scan. --all-users and other-user filters always use the scan.

- Cache hydrated terminal runs on disk (libs/cache, 60-day TTL) so repeat
  --all-status calls skip runs/get + get-output + MLflow for those ids.

The runFetcher now wraps a listStrategy (jobsScanStrategy | indexStrategy)
behind the same next(want)/exhausted contract, so the TUI, JSON, and one-shot
paths are unchanged. Also converts listModel's fetch helpers to value
receivers (fixes a recvcheck lint and a stale-`loading` guard bug).

Co-authored-by: Isaac
The index can return the same job_run_id on more than one page. Without
id-level dedup the newest-`limit` truncation counts duplicates, so
`air list --limit 20` could yield fewer than 20 unique runs. Track seen
ids and skip repeats (separate from the existing page-token loop guard).

Co-authored-by: Isaac
@riddhibhagwat-db riddhibhagwat-db merged commit cb73518 into air-cli Jul 7, 2026
22 checks passed
@riddhibhagwat-db riddhibhagwat-db deleted the air-list-fast branch July 7, 2026 02:36
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.

3 participants