@@ -90,9 +90,9 @@ type tenantSeriesSetServer struct {
90
90
91
91
ctx context.Context
92
92
93
- warnCh warnSender
94
- recv chan * storepb.Series
95
- cur * storepb.Series
93
+ directCh directSender
94
+ recv chan * storepb.Series
95
+ cur * storepb.Series
96
96
97
97
err error
98
98
tenant string
@@ -103,13 +103,13 @@ type tenantSeriesSetServer struct {
103
103
func newTenantSeriesSetServer (
104
104
ctx context.Context ,
105
105
tenant string ,
106
- warnCh warnSender ,
106
+ directCh directSender ,
107
107
) * tenantSeriesSetServer {
108
108
return & tenantSeriesSetServer {
109
- ctx : ctx ,
110
- tenant : tenant ,
111
- warnCh : warnCh ,
112
- recv : make (chan * storepb.Series ),
109
+ ctx : ctx ,
110
+ tenant : tenant ,
111
+ directCh : directCh ,
112
+ recv : make (chan * storepb.Series ),
113
113
}
114
114
}
115
115
@@ -120,27 +120,30 @@ func (s *tenantSeriesSetServer) Series(store storepb.StoreServer, r *storepb.Ser
120
120
tracing .DoInSpan (s .ctx , "multitsdb_tenant_series" , func (_ context.Context ) {
121
121
err = store .Series (r , s )
122
122
})
123
-
124
123
if err != nil {
125
124
if r .PartialResponseDisabled || r .PartialResponseStrategy == storepb .PartialResponseStrategy_ABORT {
126
125
s .err = errors .Wrapf (err , "get series for tenant %s" , s .tenant )
127
126
} else {
128
127
// Consistently prefix tenant specific warnings as done in various other places.
129
128
err = errors .New (prefixTenantWarning (s .tenant , err .Error ()))
130
- s .warnCh .send (storepb .NewWarnSeriesResponse (err ))
129
+ s .directCh .send (storepb .NewWarnSeriesResponse (err ))
131
130
}
132
131
}
133
-
134
132
close (s .recv )
135
133
}
136
134
137
135
func (s * tenantSeriesSetServer ) Send (r * storepb.SeriesResponse ) error {
138
136
series := r .GetSeries ()
139
- chunks := make ([]storepb.AggrChunk , len (series .Chunks ))
140
- copy (chunks , series .Chunks )
141
- s .recv <- & storepb.Series {
142
- Labels : series .Labels ,
143
- Chunks : chunks ,
137
+ if series == nil {
138
+ // Proxy non series responses directly to client
139
+ s .directCh .send (r )
140
+ return nil
141
+ }
142
+ // For series, pass it to our AggChunkSeriesSet.
143
+ select {
144
+ case <- s .ctx .Done ():
145
+ return s .ctx .Err ()
146
+ case s .recv <- series :
144
147
}
145
148
return nil
146
149
}
@@ -157,37 +160,39 @@ func (s *tenantSeriesSetServer) At() ([]storepb.Label, []storepb.AggrChunk) {
157
160
return s .cur .Labels , s .cur .Chunks
158
161
}
159
162
160
- func (s * tenantSeriesSetServer ) Err () error {
161
- return s .err
162
- }
163
+ func (s * tenantSeriesSetServer ) Err () error { return s .err }
163
164
164
165
// Series returns all series for a requested time range and label matcher. The
165
166
// returned data may exceed the requested time bounds. The data returned may
166
167
// have been read and merged from multiple underlying TSDBStore instances.
167
168
func (s * MultiTSDBStore ) Series (r * storepb.SeriesRequest , srv storepb.Store_SeriesServer ) error {
169
+ span , ctx := tracing .StartSpan (srv .Context (), "multitsdb_series" )
170
+ defer span .Finish ()
171
+
168
172
stores := s .tsdbStores ()
169
173
if len (stores ) == 0 {
170
174
return nil
171
175
}
172
176
173
- var (
174
- g , gctx = errgroup .WithContext (srv .Context ())
175
- span , ctx = tracing .StartSpan (gctx , "multitsdb_series" )
176
- // Allow to buffer max 10 series response.
177
- // Each might be quite large (multi chunk long series given by sidecar).
178
- respSender , respRecv , closeFn = newRespCh (gctx , 10 )
179
- )
180
- defer span .Finish ()
177
+ g , gctx := errgroup .WithContext (ctx )
178
+
179
+ // Allow to buffer max 10 series response.
180
+ // Each might be quite large (multi chunk long series given by sidecar).
181
+ respSender , respCh := newCancellableRespChannel (gctx , 10 )
181
182
182
183
g .Go (func () error {
184
+ // This go routine is responsible for calling store's Series concurrently. Merged results
185
+ // are passed to respCh and sent concurrently to client (if buffer of 10 have room).
186
+ // When this go routine finishes or is cancelled, respCh channel is closed.
187
+
183
188
var (
184
189
seriesSet []storepb.SeriesSet
185
190
wg = & sync.WaitGroup {}
186
191
)
187
192
188
193
defer func () {
189
194
wg .Wait ()
190
- closeFn ( )
195
+ close ( respCh )
191
196
}()
192
197
193
198
for tenant , store := range stores {
@@ -214,13 +219,16 @@ func (s *MultiTSDBStore) Series(r *storepb.SeriesRequest, srv storepb.Store_Seri
214
219
}
215
220
return mergedSet .Err ()
216
221
})
217
-
218
- for resp := range respRecv {
219
- if err := srv .Send (resp ); err != nil {
220
- return status .Error (codes .Unknown , errors .Wrap (err , "send series response" ).Error ())
222
+ g .Go (func () error {
223
+ // Go routine for gathering merged responses and sending them over to client. It stops when
224
+ // respCh channel is closed OR on error from client.
225
+ for resp := range respCh {
226
+ if err := srv .Send (resp ); err != nil {
227
+ return status .Error (codes .Unknown , errors .Wrap (err , "send series response" ).Error ())
228
+ }
221
229
}
222
- }
223
-
230
+ return nil
231
+ })
224
232
return g .Wait ()
225
233
}
226
234
0 commit comments