MCPcopy Index your code
hub / github.com/coder/coder / Stop

Method Stop

enterprise/coderd/prebuilds/reconcile.go:279–342  ·  view source on GitHub ↗

Stop triggers reconciler shutdown and waits for it to complete. The ctx parameter provides a timeout, if cleanup doesn't finish within this timeout, Stop() logs an error and returns.

(ctx context.Context, cause error)

Source from the content-addressed store, hash-verified

277// The ctx parameter provides a timeout, if cleanup doesn't finish within
278// this timeout, Stop() logs an error and returns.
279func (c *StoreReconciler) Stop(ctx context.Context, cause error) {
280 if cause != nil {
281 c.logger.Info(context.Background(), "stopping reconciler", slog.F("cause", cause.Error()))
282 } else {
283 c.logger.Info(context.Background(), "stopping reconciler")
284 }
285
286 // Mark the reconciler as stopped. If it was already stopped, return early.
287 // If the reconciler is running, we'll proceed to shut it down.
288 //
289 // NOTE: we need to *prospectively* mark this as stopped to prevent the
290 // reconciler from being stopped multiple times and causing problems.
291 c.mu.Lock()
292 if c.stopped {
293 c.mu.Unlock()
294 return
295 }
296 c.stopped = true
297 running := c.running
298 c.mu.Unlock()
299
300 // Unregister prebuilds state and operational metrics.
301 if c.metrics != nil && c.registerer != nil {
302 if !c.registerer.Unregister(c.metrics) {
303 // The API doesn't allow us to know why the de-registration failed, but it's not very consequential.
304 // The only time this would be an issue is if the premium license is removed, leading to the feature being
305 // disabled (and consequently this Stop method being called), and then adding a new license which enables the
306 // feature again. If the metrics cannot be registered, it'll log an error from NewStoreReconciler.
307 c.logger.Warn(context.Background(), "failed to unregister metrics collector")
308 }
309 if c.reconciliationDuration != nil {
310 if !c.registerer.Unregister(c.reconciliationDuration) {
311 c.logger.Warn(context.Background(), "failed to unregister reconciliation duration histogram")
312 }
313 }
314 }
315
316 // If the reconciler is not running, there's nothing else to do.
317 if !running {
318 return
319 }
320
321 // Trigger reconciler shutdown by canceling its internal context.
322 if c.cancelFn != nil {
323 c.cancelFn(cause)
324 }
325
326 // Wait for the reconciler to signal that it has fully exited and cleaned up.
327 select {
328 // Timeout: reconciler didn't finish cleanup within the timeout period.
329 case <-ctx.Done():
330 // nolint:gocritic // it's okay to use slog.F() for an error in this case
331 // because we want to differentiate two different types of errors: ctx.Err() and context.Cause()
332 c.logger.Error(
333 context.Background(),
334 "reconciler stop exited prematurely",
335 slog.Error(ctx.Err()),
336 slog.F("cause", context.Cause(ctx)),

Callers 2

TestRunLoopFunction · 0.95
TestReconcilerLifecycleFunction · 0.95

Calls 7

ErrMethod · 0.80
InfoMethod · 0.45
ErrorMethod · 0.45
LockMethod · 0.45
UnlockMethod · 0.45
UnregisterMethod · 0.45
DoneMethod · 0.45

Tested by 2

TestRunLoopFunction · 0.76
TestReconcilerLifecycleFunction · 0.76