Skip to content

perf(clusters): avoid eager node loading in list operations#184

Open
srnbckr wants to merge 1 commit intomainfrom
fix/clusters-lookup-perf
Open

perf(clusters): avoid eager node loading in list operations#184
srnbckr wants to merge 1 commit intomainfrom
fix/clusters-lookup-perf

Conversation

@srnbckr
Copy link
Contributor

@srnbckr srnbckr commented Feb 6, 2026

Description

Every cluster operation that called list_clusters() , including exls clusters list and the _resolve_cluster_id_callback that runs before every command with a cluster argument, eagerly loaded nodes for every cluster. For 5 clusters, exls clusters list made ~16 API calls when it only needed 1.

  • Introduce ClusterSummary base model (without nodes) and make Cluster extend it, following the list-projection vs detail-projection pattern already used in the CLI app
  • ClusterRepository.list() now returns List[ClusterSummary], skipping _load_cluster_nodes() entirely and therefore eliminates 2-3 API calls per cluster (get_cluster_nodes, list_nodes, get_cluster_resources)
  • ClusterRepository.get() still returns full Cluster with nodes, unchanged

Notes for Reviewers

For a setup with e.g. 4 clusters, this reduces the time for listing the clusters with exls from >5s to ~1s.

Before:

________________________________________________________
Executed in    5.30 secs    fish           external
   usr time    1.01 secs    0.42 millis    1.01 secs
   sys time    0.09 secs    1.08 millis    0.09 secs

After:

____________________________
Executed in    1.26 secs      fish           external
   usr time  846.58 millis    0.00 micros  846.58 millis
   sys time   64.51 millis  685.00 micros   63.82 millis

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes cluster list operations by introducing a lazy-loading pattern to avoid eagerly loading cluster nodes. For a setup with 4 clusters, this reduces the CLI execution time from ~5s to ~1s by eliminating 2-3 API calls per cluster during list operations.

Changes:

  • Introduced ClusterSummary base model (without nodes) that Cluster extends, implementing the list-projection vs detail-projection pattern
  • Updated ClusterRepository.list() to return List[ClusterSummary] instead of List[Cluster], eliminating calls to _load_cluster_nodes()
  • Updated all call sites (CLI apps, service layer, workspace provider) to use ClusterSummary for list operations while get() operations still return full Cluster with nodes

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
exls/clusters/core/domain.py Added ClusterSummary base model and made Cluster extend it with nodes field
exls/clusters/core/ports/repository.py Updated list() return type to ClusterSummary
exls/clusters/adapters/adapter.py Modified list() to create ClusterSummary objects without loading nodes
exls/clusters/core/service.py Updated list_clusters() return type and _validate_cluster_status() parameter type
exls/clusters/app.py Updated type annotations for cluster list and resolution operations
exls/services/app.py Updated type annotation for cluster resolution in service commands
exls/workspaces/adapters/provider/clusters.py Updated type annotation for cluster listing in workspace provider
tests/unit/clusters/test_clusters_service.py Added ClusterSummary test fixture and updated list_clusters test expectations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants