github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/querier/lazyquery/lazyquery.go (about) 1 package lazyquery 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/prometheus/common/model" 8 "github.com/prometheus/prometheus/pkg/labels" 9 "github.com/prometheus/prometheus/storage" 10 11 "github.com/cortexproject/cortex/pkg/chunk" 12 "github.com/cortexproject/cortex/pkg/querier/chunkstore" 13 ) 14 15 // LazyQueryable wraps a storage.Queryable 16 type LazyQueryable struct { 17 q storage.Queryable 18 } 19 20 // Querier implements storage.Queryable 21 func (lq LazyQueryable) Querier(ctx context.Context, mint, maxt int64) (storage.Querier, error) { 22 q, err := lq.q.Querier(ctx, mint, maxt) 23 if err != nil { 24 return nil, err 25 } 26 27 return NewLazyQuerier(q), nil 28 } 29 30 // NewLazyQueryable returns a lazily wrapped queryable 31 func NewLazyQueryable(q storage.Queryable) storage.Queryable { 32 return LazyQueryable{q} 33 } 34 35 // LazyQuerier is a lazy-loaded adapter for a storage.Querier 36 type LazyQuerier struct { 37 next storage.Querier 38 } 39 40 // NewLazyQuerier wraps a storage.Querier, does the Select in the background. 41 // Return value cannot be used from more than one goroutine simultaneously. 42 func NewLazyQuerier(next storage.Querier) storage.Querier { 43 return LazyQuerier{next} 44 } 45 46 // Select implements Storage.Querier 47 func (l LazyQuerier) Select(selectSorted bool, params *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet { 48 // make sure there is space in the buffer, to unblock the goroutine and let it die even if nobody is 49 // waiting for the result yet (or anymore). 50 future := make(chan storage.SeriesSet, 1) 51 go func() { 52 future <- l.next.Select(selectSorted, params, matchers...) 53 }() 54 55 return &lazySeriesSet{ 56 future: future, 57 } 58 } 59 60 // LabelValues implements Storage.Querier 61 func (l LazyQuerier) LabelValues(name string, matchers ...*labels.Matcher) ([]string, storage.Warnings, error) { 62 return l.next.LabelValues(name, matchers...) 63 } 64 65 // LabelNames implements Storage.Querier 66 func (l LazyQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) { 67 return l.next.LabelNames(matchers...) 68 } 69 70 // Close implements Storage.Querier 71 func (l LazyQuerier) Close() error { 72 return l.next.Close() 73 } 74 75 // Get implements chunk.Store for the chunk tar HTTP handler. 76 func (l LazyQuerier) Get(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) ([]chunk.Chunk, error) { 77 store, ok := l.next.(chunkstore.ChunkStore) 78 if !ok { 79 return nil, fmt.Errorf("not supported") 80 } 81 82 return store.Get(ctx, userID, from, through, matchers...) 83 } 84 85 type lazySeriesSet struct { 86 next storage.SeriesSet 87 future chan storage.SeriesSet 88 } 89 90 // Next implements storage.SeriesSet. NB not thread safe! 91 func (s *lazySeriesSet) Next() bool { 92 if s.next == nil { 93 s.next = <-s.future 94 } 95 return s.next.Next() 96 } 97 98 // At implements storage.SeriesSet. 99 func (s *lazySeriesSet) At() storage.Series { 100 if s.next == nil { 101 s.next = <-s.future 102 } 103 return s.next.At() 104 } 105 106 // Err implements storage.SeriesSet. 107 func (s *lazySeriesSet) Err() error { 108 if s.next == nil { 109 s.next = <-s.future 110 } 111 return s.next.Err() 112 } 113 114 // Warnings implements storage.SeriesSet. 115 func (s *lazySeriesSet) Warnings() storage.Warnings { 116 return nil 117 }