| 575 | } |
| 576 | |
| 577 | func (api *API) watcherLoop() { |
| 578 | defer close(api.watcherDone) |
| 579 | defer api.logger.Debug(api.ctx, "watcher loop stopped") |
| 580 | api.logger.Debug(api.ctx, "watcher loop started") |
| 581 | |
| 582 | for { |
| 583 | event, err := api.watcher.Next(api.ctx) |
| 584 | if err != nil { |
| 585 | if errors.Is(err, watcher.ErrClosed) { |
| 586 | api.logger.Debug(api.ctx, "watcher closed") |
| 587 | return |
| 588 | } |
| 589 | if api.ctx.Err() != nil { |
| 590 | api.logger.Debug(api.ctx, "api context canceled") |
| 591 | return |
| 592 | } |
| 593 | api.logger.Error(api.ctx, "watcher error waiting for next event", slog.Error(err)) |
| 594 | continue |
| 595 | } |
| 596 | if event == nil { |
| 597 | continue |
| 598 | } |
| 599 | |
| 600 | now := api.clock.Now("agentcontainers", "watcherLoop") |
| 601 | switch { |
| 602 | case event.Has(fsnotify.Create | fsnotify.Write): |
| 603 | api.logger.Debug(api.ctx, "devcontainer config file changed", slog.F("file", event.Name)) |
| 604 | api.markDevcontainerDirty(event.Name, now) |
| 605 | case event.Has(fsnotify.Remove): |
| 606 | api.logger.Debug(api.ctx, "devcontainer config file removed", slog.F("file", event.Name)) |
| 607 | api.markDevcontainerDirty(event.Name, now) |
| 608 | case event.Has(fsnotify.Rename): |
| 609 | api.logger.Debug(api.ctx, "devcontainer config file renamed", slog.F("file", event.Name)) |
| 610 | api.markDevcontainerDirty(event.Name, now) |
| 611 | default: |
| 612 | api.logger.Debug(api.ctx, "devcontainer config file event ignored", slog.F("file", event.Name), slog.F("event", event)) |
| 613 | } |
| 614 | } |
| 615 | } |
| 616 | |
| 617 | // updaterLoop is responsible for periodically updating the container |
| 618 | // list and handling manual refresh requests. |