MCPcopy Create free account
hub / github.com/devnullvoid/pvetui / enrichGroupNodesParallel

Method enrichGroupNodesParallel

internal/ui/components/refresh.go:469–587  ·  view source on GitHub ↗

enrichGroupNodesParallel enriches group node data in parallel and finalizes the refresh. token is the generation token that must be passed to endRefresh when enrichment completes.

(token uint64, nodes []*api.Node, hasSelectedNode bool, selectedNodeName string, hasSelectedVM bool, selectedVMID int, selectedVMNode string, searchWasActive bool, isInitialLoad bool)

Source from the content-addressed store, hash-verified

467// enrichGroupNodesParallel enriches group node data in parallel and finalizes the refresh.
468// token is the generation token that must be passed to endRefresh when enrichment completes.
469func (a *App) enrichGroupNodesParallel(token uint64, nodes []*api.Node, hasSelectedNode bool, selectedNodeName string, hasSelectedVM bool, selectedVMID int, selectedVMNode string, searchWasActive bool, isInitialLoad bool) {
470 go func() {
471 var wg sync.WaitGroup
472
473 // Start loading tasks in parallel with node enrichment (independent operation)
474 a.loadTasksData()
475
476 // Snapshot connection state under lock so reads are race-free.
477 conn := a.snapConn()
478
479 // Accumulate enriched nodes into a local slice to avoid data races.
480 // Concurrent goroutines write to their own index; the slice is swapped into
481 // GlobalState inside QueueUpdateDraw after all goroutines complete.
482 enrichedNodes := make([]*api.Node, len(nodes))
483 copy(enrichedNodes, nodes)
484
485 // Create a context for the enrichment process
486 ctx := context.Background()
487
488 // Enrich nodes in parallel
489 for i, node := range nodes {
490 if node == nil || node.SourceProfile == "" {
491 continue
492 }
493
494 wg.Add(1)
495 go func(idx int, n *api.Node) {
496 defer wg.Done()
497
498 // Fetch the node status from the specific profile's client
499 freshNode, err := conn.groupManager.GetNodeFromGroup(ctx, n.SourceProfile, n.Name)
500
501 if err == nil && freshNode != nil {
502 // Ensure Online status is set to true if we got a response
503 freshNode.Online = true
504
505 // Preserve VMs from the existing node list
506 if nodes[idx] != nil {
507 freshNode.VMs = nodes[idx].VMs
508 // Preserve IP if missing in freshNode
509 if freshNode.IP == "" {
510 freshNode.IP = nodes[idx].IP
511 }
512 // Preserve ID if missing in freshNode
513 if freshNode.ID == "" {
514 freshNode.ID = nodes[idx].ID
515 }
516 // Preserve Storage if missing in freshNode
517 if freshNode.Storage == nil && nodes[idx].Storage != nil {
518 freshNode.Storage = nodes[idx].Storage
519 }
520 }
521
522 // Ensure SourceProfile is preserved
523 freshNode.SourceProfile = n.SourceProfile
524
525 // Write to local slice only — no GlobalState mutation from goroutines.
526 enrichedNodes[idx] = freshNode

Callers 2

doManualRefreshMethod · 0.95
switchToGroupMethod · 0.95

Calls 15

loadTasksDataMethod · 0.95
snapConnMethod · 0.95
createSyntheticGroupMethod · 0.95
restoreSelectionMethod · 0.95
restoreSearchUIMethod · 0.95
getDisplayClusterMethod · 0.95
endRefreshMethod · 0.95
FilterNodesFunction · 0.92
GetNodeFromGroupMethod · 0.80
QueueUpdateDrawMethod · 0.80
GetSearchStateMethod · 0.80

Tested by

no test coverage detected