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

Method updaterLoop

agent/agentcontainers/api.go:619–701  ·  view source on GitHub ↗

updaterLoop is responsible for periodically updating the container list and handling manual refresh requests.

()

Source from the content-addressed store, hash-verified

617// updaterLoop is responsible for periodically updating the container
618// list and handling manual refresh requests.
619func (api *API) updaterLoop() {
620 defer close(api.updaterDone)
621 defer api.logger.Debug(api.ctx, "updater loop stopped")
622 api.logger.Debug(api.ctx, "updater loop started")
623
624 // Make sure we clean up any subagents not tracked by this process
625 // before starting the update loop and creating new ones.
626 api.logger.Debug(api.ctx, "cleaning up subagents")
627 if err := api.cleanupSubAgents(api.ctx); err != nil {
628 api.logger.Error(api.ctx, "cleanup subagents failed", slog.Error(err))
629 } else {
630 api.logger.Debug(api.ctx, "cleanup subagents complete")
631 }
632
633 // Perform an initial update to populate the container list, this
634 // gives us a guarantee that the API has loaded the initial state
635 // before returning any responses. This is useful for both tests
636 // and anyone looking to interact with the API.
637 api.logger.Debug(api.ctx, "performing initial containers update")
638 if err := api.updateContainers(api.ctx); err != nil {
639 if errors.Is(err, context.Canceled) {
640 api.logger.Warn(api.ctx, "initial containers update canceled", slog.Error(err))
641 } else {
642 api.logger.Error(api.ctx, "initial containers update failed", slog.Error(err))
643 }
644 } else {
645 api.logger.Debug(api.ctx, "initial containers update complete")
646 }
647 close(api.initialUpdateDone)
648
649 // We utilize a TickerFunc here instead of a regular Ticker so that
650 // we can guarantee execution of the updateContainers method after
651 // advancing the clock.
652 var prevErr error
653 ticker := api.clock.TickerFunc(api.ctx, api.updateInterval, func() error {
654 done := make(chan error, 1)
655 var sent bool
656 defer func() {
657 if !sent {
658 close(done)
659 }
660 }()
661 select {
662 case <-api.ctx.Done():
663 return api.ctx.Err()
664 case api.updateTrigger <- done:
665 sent = true
666 err := <-done
667 if err != nil {
668 if errors.Is(err, context.Canceled) {
669 api.logger.Warn(api.ctx, "updater loop ticker canceled", slog.Error(err))
670 return nil
671 }
672 // Avoid excessive logging of the same error.
673 if prevErr == nil || prevErr.Error() != err.Error() {
674 api.logger.Error(api.ctx, "updater loop ticker failed", slog.Error(err))
675 }
676 prevErr = err

Callers 1

StartMethod · 0.95

Calls 7

cleanupSubAgentsMethod · 0.95
updateContainersMethod · 0.95
ErrMethod · 0.80
WaitMethod · 0.65
ErrorMethod · 0.45
IsMethod · 0.45
DoneMethod · 0.45

Tested by

no test coverage detected