code: func (p *PartitionedMemoryIdx) FindTagValues(orgId uint32, tag string, prefix string, expressions []string, from int64, limit uint) ([]string, error) {
  	g, _ := errgroup.WithContext(context.Background())
  	result := make([][]string, len(p.Partition))
  	var i int
  	for _, m := range p.Partition {
  		pos, m := i, m
  		g.Go(func() error {
  			found, err := m.FindTagValues(orgId, tag, prefix, expressions, from, limit)
  			if err != nil {
  				return err
  			}
  			result[pos] = found
  			return nil
  		})
  		i++
  	}
  	if err := g.Wait(); err != nil {
  		log.Errorf("memory-idx: failed to FindTagValues: orgId=%d tag=%s prefix=%s expressions=%v from=%d limit=%d. %s", orgId, tag, prefix, expressions, from, limit, err)
  		return nil, err
  	}
  
  	// merge our results into the unique set of tags
  	merged := map[string]struct{}{}
  	for _, tags := range result {
  		for _, t := range tags {
  			merged[t] = struct{}{}
  		}
  	}
  	response := make([]string, 0, len(merged))
  	for tag := range merged {
  		response = append(response, tag)
  	}
  
  	return response, nil
  }
docs: // FindTagValues generates a list of possible values that could
  // complete a given value prefix. It requires a tag to be specified and only values
  // of the given tag will be returned. It also accepts additional conditions to
  // further narrow down the result set in the format of graphite's tag queries