func()

in local-container-endpoints/handlers/metadata.go [137:176]


func (service *MetadataService) taskStatsResponse(w http.ResponseWriter, identifier string, callerIP string) error {
	timeout, _ := time.ParseDuration(config.HTTPTimeoutDuration)
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	containers, err := service.dockerClient.ContainerList(ctx)
	if err != nil {
		return err
	}
	response := make(map[string]types.Stats)

	statsChan := make(chan dockerStats, len(containers))

	for _, container := range containers {
		go service.getContainerStatsWithChannel(ctx, statsChan, container.ID)
	}

	for range containers {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case stats := <-statsChan:
			if stats.err != nil {
				// cancel the context
				cancel()
				// Question for @sharanyad and @clareliguori: it's safe to return here, right?
				// Any remaining goroutines will write to the buffered channel, and terminate.
				// Then the buffered channel will get garbage collected.
				// Also calling cancel() ends the context,
				// so none of the Docker API requests can get stuck.
				// This also applies for the above case where we return ctx.Err().
				return stats.err
			}
			response[stats.containerID] = *stats.stats
		}
	}

	writeJSONResponse(w, response)
	return nil
}