updateContainers fetches the latest container list, processes it, and updates the cache. It performs locking for updating shared API state.
(ctx context.Context)
| 851 | // updateContainers fetches the latest container list, processes it, and |
| 852 | // updates the cache. It performs locking for updating shared API state. |
| 853 | func (api *API) updateContainers(ctx context.Context) error { |
| 854 | listCtx, listCancel := context.WithTimeout(ctx, defaultOperationTimeout) |
| 855 | defer listCancel() |
| 856 | |
| 857 | updated, err := api.ccli.List(listCtx) |
| 858 | if err != nil { |
| 859 | // If the context was canceled, we hold off on clearing the |
| 860 | // containers cache. This is to avoid clearing the cache if |
| 861 | // the update was canceled due to a timeout. Hopefully this |
| 862 | // will clear up on the next update. |
| 863 | if !errors.Is(err, context.Canceled) { |
| 864 | api.mu.Lock() |
| 865 | api.containersErr = err |
| 866 | api.mu.Unlock() |
| 867 | } |
| 868 | |
| 869 | return xerrors.Errorf("list containers failed: %w", err) |
| 870 | } |
| 871 | // Clone to avoid test flakes due to data manipulation. |
| 872 | updated.Containers = slices.Clone(updated.Containers) |
| 873 | |
| 874 | api.mu.Lock() |
| 875 | defer api.mu.Unlock() |
| 876 | |
| 877 | var previouslyKnownDevcontainers map[string]codersdk.WorkspaceAgentDevcontainer |
| 878 | if len(api.updateChans) > 0 { |
| 879 | previouslyKnownDevcontainers = maps.Clone(api.knownDevcontainers) |
| 880 | } |
| 881 | |
| 882 | api.processUpdatedContainersLocked(ctx, updated) |
| 883 | |
| 884 | if len(api.updateChans) > 0 { |
| 885 | statesAreEqual := maps.EqualFunc( |
| 886 | previouslyKnownDevcontainers, |
| 887 | api.knownDevcontainers, |
| 888 | func(dc1, dc2 codersdk.WorkspaceAgentDevcontainer) bool { |
| 889 | return dc1.Equals(dc2) |
| 890 | }) |
| 891 | |
| 892 | if !statesAreEqual { |
| 893 | api.broadcastUpdatesLocked() |
| 894 | } |
| 895 | } |
| 896 | |
| 897 | api.logger.Debug(ctx, "containers updated successfully", slog.F("container_count", len(api.containers.Containers)), slog.F("warning_count", len(api.containers.Warnings)), slog.F("devcontainer_count", len(api.knownDevcontainers))) |
| 898 | |
| 899 | return nil |
| 900 | } |
| 901 | |
| 902 | // processUpdatedContainersLocked updates the devcontainer state based |
| 903 | // on the latest list of containers. This method assumes that api.mu is |
no test coverage detected