doFastRefresh is the implementation of fast refresh. Callers that already hold a generation token (e.g. profile switches via forceNewRefresh) should call this directly instead of acquiring a new token first. This is used for profile switching where perceived speed matters most — the user sees node a
(token uint64)
| 158 | // the user sees node and guest lists right away, then details (CPU, filesystems, guest agent) |
| 159 | // fill in progressively. |
| 160 | func (a *App) doFastRefresh(token uint64) { |
| 161 | if models.GlobalState.HasPendingOperations() { |
| 162 | a.endRefresh(token) |
| 163 | a.showMessageSafe("Cannot refresh data while there are pending operations in progress") |
| 164 | return |
| 165 | } |
| 166 | |
| 167 | a.header.ShowLoading("Loading data...") |
| 168 | a.footer.SetLoading(true) |
| 169 | |
| 170 | go func() { |
| 171 | // Snapshot connection state under lock so reads are race-free. |
| 172 | conn := a.snapConn() |
| 173 | |
| 174 | if conn.isGroupMode { |
| 175 | // Group mode: delegate to manual refresh internal logic (already shows data before enrichment). |
| 176 | // We already hold the refresh token, so pass it through directly. |
| 177 | a.doManualRefresh(token) |
| 178 | return |
| 179 | } |
| 180 | |
| 181 | // Capture the client instance that is starting this refresh. |
| 182 | // Used for making API calls with the correct client during enrichment. |
| 183 | refreshClient := conn.client |
| 184 | |
| 185 | // Single profile: get basic data fast (no VM enrichment), show it, then enrich in background |
| 186 | cluster, err := refreshClient.GetFastFreshClusterStatus(func(enrichErr error) { |
| 187 | // VM enrichment complete callback — update VM list with enriched data |
| 188 | a.QueueUpdateDraw(func() { |
| 189 | // Stale guard: abort only if a *newer* refresh has superseded this one. |
| 190 | // refreshGen == 0 means this refresh completed normally via endRefresh — |
| 191 | // we still need to run to clear the header loading indicator and update |
| 192 | // VM details (doEnrichNodes calls endRefresh before this callback fires). |
| 193 | if current := a.refreshGen.Load(); current != 0 && current != token { |
| 194 | return |
| 195 | } |
| 196 | |
| 197 | if refreshClient.Cluster == nil { |
| 198 | return |
| 199 | } |
| 200 | |
| 201 | // Rebuild VM list from enriched cluster data |
| 202 | var enrichedVMs []*api.VM |
| 203 | for _, node := range refreshClient.Cluster.Nodes { |
| 204 | if node != nil { |
| 205 | for _, vm := range node.VMs { |
| 206 | if vm != nil { |
| 207 | enrichedVMs = append(enrichedVMs, vm) |
| 208 | } |
| 209 | } |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | if len(enrichedVMs) > 0 { |
| 214 | // Preserve current VM selection |
| 215 | var selectedVMID int |
| 216 | var selectedVMNode string |
| 217 | var hasSelectedVM bool |
no test coverage detected