code: func (d *Discovery) refresh(ctx context.Context, ch chan<- []*targetgroup.Group) {
  	t0 := time.Now()
  	defer func() {
  		fileSDScanDuration.Observe(time.Since(t0).Seconds())
  	}()
  	ref := map[string]int{}
  	for _, p := range d.listFiles() {
  		tgroups, err := d.readFile(p)
  		if err != nil {
  			fileSDReadErrorsCount.Inc()
  
  			level.Error(d.logger).Log("msg", "Error reading file", "path", p, "err", err)
  			// Prevent deletion down below.
  			ref[p] = d.lastRefresh[p]
  			continue
  		}
  		select {
  		case ch <- tgroups:
  		case <-ctx.Done():
  			return
  		}
  
  		ref[p] = len(tgroups)
  	}
  	// Send empty updates for sources that disappeared.
  	for f, n := range d.lastRefresh {
  		m, ok := ref[f]
  		if !ok || n > m {
  			level.Debug(d.logger).Log("msg", "file_sd refresh found file that should be removed", "file", f)
  			d.deleteTimestamp(f)
  			for i := m; i < n; i++ {
  				select {
  				case ch <- []*targetgroup.Group{{Source: fileSource(f, i)}}:
  				case <-ctx.Done():
  					return
  				}
  			}
  		}
  	}
  	d.lastRefresh = ref
  
  	d.watchFiles()
  }
docs: // refresh reads all files matching the discovery's patterns and sends the respective
  // updated target groups through the channel.