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 }