()
| 157 | } |
| 158 | |
| 159 | func (sm *StatusManager) close() error { |
| 160 | sm.cancel() |
| 161 | |
| 162 | componentNames := sm.getAllComponents() |
| 163 | |
| 164 | for i, j := 0, len(componentNames)-1; i < j; i, j = i+1, j-1 { |
| 165 | componentNames[i], componentNames[j] = componentNames[j], componentNames[i] |
| 166 | } |
| 167 | |
| 168 | shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), sm.config.ShutdownTimeout) |
| 169 | deadline, _ := shutdownCtx.Deadline() |
| 170 | |
| 171 | doneCh := make(chan struct{}) |
| 172 | go func() { |
| 173 | sm.shutdownComponents(shutdownCtx, componentNames) |
| 174 | close(doneCh) |
| 175 | }() |
| 176 | |
| 177 | var shutdownErr error |
| 178 | select { |
| 179 | case <-doneCh: |
| 180 | case <-shutdownCtx.Done(): |
| 181 | shutdownErr = fmt.Errorf("timeout stopping components") |
| 182 | } |
| 183 | |
| 184 | shutdownCancel() |
| 185 | |
| 186 | if err := sm.waitForGoroutines(deadline); err != nil { |
| 187 | if shutdownErr != nil { |
| 188 | shutdownErr = fmt.Errorf("%v; %w", shutdownErr, err) |
| 189 | } else { |
| 190 | shutdownErr = err |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | return shutdownErr |
| 195 | } |
| 196 | |
| 197 | func (sm *StatusManager) shutdownComponents(ctx context.Context, order []string) { |
| 198 | if len(order) == 0 { |
no test coverage detected