@@ -111,30 +111,53 @@ func (c *Controller) stopAppWorker(appName string) {
111111 return
112112 }
113113
114- // 1) Delete VMs referencing this application
114+ // 1) Delete VMs referencing this application, grouped by component.
115115 var appVMs []v1.VirtualMachine
116116 if err := db .DB .Where ("application = ?" , appName ).Find (& appVMs ).Error ; err != nil {
117117 log .Printf ("stopAppWorker: failed to list VMs for app %s: %v" , appName , err )
118118 } else {
119+ // Group VMs by component name (empty string for none)
120+ vmsByComp := make (map [string ][]v1.VirtualMachine )
121+ var compOrder []string
119122 for _ , vm := range appVMs {
120- log .Printf ("stopAppWorker: removing VM %s" , vm .Metadata .Name )
121- if vm .CloudStackID != "" {
122- // Check if VM still exists in CloudStack before attempting deletion
123- params := c .csClient .VirtualMachine .NewListVirtualMachinesParams ()
124- params .SetId (vm .CloudStackID )
125- resp , _ := c .csClient .VirtualMachine .ListVirtualMachines (params )
126- if resp != nil && len (resp .VirtualMachines ) > 0 {
127- dp := c .csClient .VirtualMachine .NewDestroyVirtualMachineParams (vm .CloudStackID )
128- dp .SetExpunge (true )
129- if _ , err := c .csClient .VirtualMachine .DestroyVirtualMachine (dp ); err != nil {
130- log .Printf ("stopAppWorker: failed to destroy CloudStack VM %s (id=%s): %v" , vm .Metadata .Name , vm .CloudStackID , err )
131- return
132- }
133- }
123+ comp := vm .Component
124+ if _ , ok := vmsByComp [comp ]; ! ok {
125+ compOrder = append (compOrder , comp )
134126 }
135- if err := db .DB .Delete (& vm ).Error ; err != nil {
136- log .Printf ("stopAppWorker: failed to delete VM record %s: %v" , vm .Metadata .Name , err )
127+ vmsByComp [comp ] = append (vmsByComp [comp ], vm )
128+ }
129+
130+ // Process components in deterministic order, deleting each component's VMs in parallel
131+ for _ , comp := range compOrder {
132+ vms := vmsByComp [comp ]
133+ log .Printf ("stopAppWorker: removing %d VMs for component '%s'" , len (vms ), comp )
134+ var wg sync.WaitGroup
135+ for _ , vm := range vms {
136+ wg .Add (1 )
137+ vmCopy := vm
138+ go func (v v1.VirtualMachine ) {
139+ defer wg .Done ()
140+ log .Printf ("stopAppWorker: removing VM %s" , v .Metadata .Name )
141+ if v .CloudStackID != "" {
142+ // Check if VM still exists in CloudStack before attempting deletion
143+ params := c .csClient .VirtualMachine .NewListVirtualMachinesParams ()
144+ params .SetId (v .CloudStackID )
145+ resp , _ := c .csClient .VirtualMachine .ListVirtualMachines (params )
146+ if resp != nil && len (resp .VirtualMachines ) > 0 {
147+ dp := c .csClient .VirtualMachine .NewDestroyVirtualMachineParams (v .CloudStackID )
148+ dp .SetExpunge (true )
149+ if _ , err := c .csClient .VirtualMachine .DestroyVirtualMachine (dp ); err != nil {
150+ log .Printf ("stopAppWorker: failed to destroy CloudStack VM %s (id=%s): %v" , v .Metadata .Name , v .CloudStackID , err )
151+ return
152+ }
153+ }
154+ }
155+ if err := db .DB .Delete (& v ).Error ; err != nil {
156+ log .Printf ("stopAppWorker: failed to delete VM record %s: %v" , v .Metadata .Name , err )
157+ }
158+ }(vmCopy )
137159 }
160+ wg .Wait ()
138161 }
139162 }
140163
0 commit comments