github.com/thanos-io/thanos@v0.32.5/pkg/store/flushable.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package store
     5  
     6  import (
     7  	"github.com/prometheus/prometheus/model/labels"
     8  	"golang.org/x/exp/slices"
     9  
    10  	"github.com/thanos-io/thanos/pkg/store/labelpb"
    11  	"github.com/thanos-io/thanos/pkg/store/storepb"
    12  )
    13  
    14  type sortingStrategy uint64
    15  
    16  const (
    17  	sortingStrategyStore sortingStrategy = iota + 1
    18  	sortingStrategyNone
    19  )
    20  
    21  // flushableServer is an extension of storepb.Store_SeriesServer with a Flush method.
    22  type flushableServer interface {
    23  	storepb.Store_SeriesServer
    24  
    25  	Flush() error
    26  }
    27  
    28  func newFlushableServer(
    29  	upstream storepb.Store_SeriesServer,
    30  	sortingsortingStrategy sortingStrategy,
    31  ) flushableServer {
    32  	switch sortingsortingStrategy {
    33  	case sortingStrategyStore:
    34  		return &resortingServer{Store_SeriesServer: upstream}
    35  	case sortingStrategyNone:
    36  		return &passthroughServer{Store_SeriesServer: upstream}
    37  	default:
    38  		// should not happen.
    39  		panic("unexpected sorting strategy")
    40  	}
    41  }
    42  
    43  // passthroughServer is a flushableServer that forwards all data to
    44  // an upstream server without additional processing.
    45  type passthroughServer struct {
    46  	storepb.Store_SeriesServer
    47  }
    48  
    49  func (p *passthroughServer) Flush() error { return nil }
    50  
    51  // resortingServer is a flushableServer that resorts all series by their labels.
    52  // This is required if replica labels are stored internally in a TSDB.
    53  // Data is resorted and sent to an upstream server upon calling Flush.
    54  type resortingServer struct {
    55  	storepb.Store_SeriesServer
    56  	series []*storepb.Series
    57  }
    58  
    59  func (r *resortingServer) Send(response *storepb.SeriesResponse) error {
    60  	if response.GetSeries() == nil {
    61  		return r.Store_SeriesServer.Send(response)
    62  	}
    63  
    64  	series := response.GetSeries()
    65  	labelpb.ReAllocZLabelsStrings(&series.Labels, false)
    66  	r.series = append(r.series, series)
    67  	return nil
    68  }
    69  
    70  func (r *resortingServer) Flush() error {
    71  	slices.SortFunc(r.series, func(a, b *storepb.Series) bool {
    72  		return labels.Compare(
    73  			labelpb.ZLabelsToPromLabels(a.Labels),
    74  			labelpb.ZLabelsToPromLabels(b.Labels),
    75  		) < 0
    76  	})
    77  	for _, response := range r.series {
    78  		if err := r.Store_SeriesServer.Send(storepb.NewSeriesResponse(response)); err != nil {
    79  			return err
    80  		}
    81  	}
    82  	return nil
    83  }