4
4
package store
5
5
6
6
import (
7
+ "context"
7
8
"fmt"
8
9
"io/ioutil"
9
10
"math"
10
11
"math/rand"
11
12
"os"
12
13
"path/filepath"
13
14
"testing"
15
+ "time"
14
16
17
+ "github.com/fortytw2/leaktest"
15
18
"github.com/go-kit/kit/log"
19
+ "github.com/prometheus/prometheus/pkg/labels"
16
20
"github.com/prometheus/prometheus/tsdb"
17
21
"github.com/thanos-io/thanos/pkg/component"
18
22
"github.com/thanos-io/thanos/pkg/store/storepb"
@@ -21,6 +25,8 @@ import (
21
25
)
22
26
23
27
func TestMultiTSDBSeries (t * testing.T ) {
28
+ defer leaktest .CheckTimeout (t , 10 * time .Second )()
29
+
24
30
tb := testutil .NewTB (t )
25
31
storetestutil .RunSeriesInterestingCases (tb , 200e3 , 200e3 , func (t testutil.TB , samplesPerSeries , series int ) {
26
32
if ok := t .Run ("headOnly" , func (t testutil.TB ) {
@@ -116,12 +122,12 @@ func benchMultiTSDBSeries(t testutil.TB, totalSamples, totalSeries int, flushToB
116
122
dbs [j ] = & mockedStartTimeDB {DBReadOnly : db , startTime : int64 (j * samplesPerSeriesPerTSDB * seriesPerTSDB )}
117
123
}
118
124
119
- tsdbs := map [string ]* TSDBStore {}
125
+ tsdbs := map [string ]storepb. StoreServer {}
120
126
for i , db := range dbs {
121
127
tsdbs [fmt .Sprintf ("%v" , i )] = & TSDBStore {db : db , logger : logger }
122
128
}
123
129
124
- store := NewMultiTSDBStore (logger , nil , component .Receive , func () map [string ]* TSDBStore { return tsdbs })
130
+ store := NewMultiTSDBStore (logger , nil , component .Receive , func () map [string ]storepb. StoreServer { return tsdbs })
125
131
126
132
var expected []storepb.Series
127
133
lastLabels := storepb.Series {}
@@ -154,3 +160,135 @@ func benchMultiTSDBSeries(t testutil.TB, totalSamples, totalSeries int, flushToB
154
160
},
155
161
)
156
162
}
163
+
164
+ type mockedStoreServer struct {
165
+ storepb.StoreServer
166
+
167
+ responses []* storepb.SeriesResponse
168
+ }
169
+
170
+ func (m * mockedStoreServer ) Series (_ * storepb.SeriesRequest , server storepb.Store_SeriesServer ) error {
171
+ for _ , r := range m .responses {
172
+ if err := server .Send (r ); err != nil {
173
+ return err
174
+ }
175
+ }
176
+ return nil
177
+ }
178
+
179
+ // Regression test against https://github.com/thanos-io/thanos/issues/2823.
180
+ func TestTenantSeriesSetServert_NotLeakingIfNotExhausted (t * testing.T ) {
181
+ t .Run ("exhausted StoreSet" , func (t * testing.T ) {
182
+ defer leaktest .CheckTimeout (t , 10 * time .Second )()
183
+
184
+ s := newTenantSeriesSetServer (context .Background (), "a" , nil )
185
+
186
+ resps := []* storepb.SeriesResponse {
187
+ storeSeriesResponse (t , labels .FromStrings ("a" , "a" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
188
+ storeSeriesResponse (t , labels .FromStrings ("a" , "b" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
189
+ storeSeriesResponse (t , labels .FromStrings ("a" , "c" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
190
+ }
191
+
192
+ m := & mockedStoreServer {responses : resps }
193
+
194
+ go func () {
195
+ s .Series (m , & storepb.SeriesRequest {PartialResponseStrategy : storepb .PartialResponseStrategy_ABORT })
196
+ }()
197
+
198
+ testutil .Ok (t , s .Err ())
199
+ i := 0
200
+ for s .Next () {
201
+ l , c := s .At ()
202
+
203
+ testutil .Equals (t , resps [i ].GetSeries ().Labels , l )
204
+ testutil .Equals (t , resps [i ].GetSeries ().Chunks , c )
205
+
206
+ i ++
207
+ }
208
+ testutil .Ok (t , s .Err ())
209
+ testutil .Equals (t , 3 , i )
210
+ })
211
+
212
+ t .Run ("cancelled, not exhausted StoreSet" , func (t * testing.T ) {
213
+ defer leaktest .CheckTimeout (t , 10 * time .Second )()
214
+
215
+ ctx , cancel := context .WithCancel (context .Background ())
216
+ s := newTenantSeriesSetServer (ctx , "a" , nil )
217
+
218
+ m := & mockedStoreServer {responses : []* storepb.SeriesResponse {
219
+ storeSeriesResponse (t , labels .FromStrings ("a" , "a" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
220
+ storeSeriesResponse (t , labels .FromStrings ("a" , "b" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
221
+ storeSeriesResponse (t , labels .FromStrings ("a" , "c" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
222
+ }}
223
+ go func () {
224
+ s .Series (m , & storepb.SeriesRequest {PartialResponseStrategy : storepb .PartialResponseStrategy_ABORT })
225
+ }()
226
+
227
+ testutil .Ok (t , s .Err ())
228
+ testutil .Equals (t , true , s .Next ())
229
+ cancel ()
230
+ })
231
+ }
232
+
233
+ type mockedSeriesServer struct {
234
+ storepb.Store_SeriesServer
235
+ ctx context.Context
236
+
237
+ send func (* storepb.SeriesResponse ) error
238
+ }
239
+
240
+ func (s * mockedSeriesServer ) Send (r * storepb.SeriesResponse ) error {
241
+ return s .send (r )
242
+ }
243
+ func (s * mockedSeriesServer ) Context () context.Context { return s .ctx }
244
+
245
+ // Regression test against https://github.com/thanos-io/thanos/issues/2823.
246
+ // This is different leak than in TestTenantSeriesSetServert_NotLeakingIfNotExhausted
247
+ func TestMultiTSDBStore_NotLeakingOnPrematureFinish (t * testing.T ) {
248
+ defer leaktest .CheckTimeout (t , 10 * time .Second )()
249
+
250
+ m := NewMultiTSDBStore (log .NewNopLogger (), nil , component .Receive , func () map [string ]storepb.StoreServer {
251
+ return map [string ]storepb.StoreServer {
252
+ // Ensure more than 10 (internal respCh channel).
253
+ "a" : & mockedStoreServer {responses : []* storepb.SeriesResponse {
254
+ storeSeriesResponse (t , labels .FromStrings ("a" , "a" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
255
+ storeSeriesResponse (t , labels .FromStrings ("a" , "b" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
256
+ storeSeriesResponse (t , labels .FromStrings ("a" , "c" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
257
+ storeSeriesResponse (t , labels .FromStrings ("a" , "d" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
258
+ storeSeriesResponse (t , labels .FromStrings ("a" , "e" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
259
+ storeSeriesResponse (t , labels .FromStrings ("a" , "f" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
260
+ storeSeriesResponse (t , labels .FromStrings ("a" , "g" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
261
+ storeSeriesResponse (t , labels .FromStrings ("a" , "h" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
262
+ storeSeriesResponse (t , labels .FromStrings ("a" , "i" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
263
+ storeSeriesResponse (t , labels .FromStrings ("a" , "j" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
264
+ }},
265
+ "b" : & mockedStoreServer {responses : []* storepb.SeriesResponse {
266
+ storeSeriesResponse (t , labels .FromStrings ("b" , "a" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
267
+ storeSeriesResponse (t , labels .FromStrings ("b" , "b" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
268
+ storeSeriesResponse (t , labels .FromStrings ("b" , "c" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
269
+ storeSeriesResponse (t , labels .FromStrings ("b" , "d" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
270
+ storeSeriesResponse (t , labels .FromStrings ("b" , "e" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
271
+ storeSeriesResponse (t , labels .FromStrings ("b" , "f" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
272
+ storeSeriesResponse (t , labels .FromStrings ("b" , "g" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
273
+ storeSeriesResponse (t , labels .FromStrings ("b" , "h" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
274
+ storeSeriesResponse (t , labels .FromStrings ("b" , "i" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
275
+ storeSeriesResponse (t , labels .FromStrings ("b" , "j" ), []sample {{0 , 0 }, {2 , 1 }, {3 , 2 }}),
276
+ }},
277
+ }
278
+ })
279
+
280
+ if ok := t .Run ("failing send" , func (t * testing.T ) {
281
+ ctx , cancel := context .WithCancel (context .Background ())
282
+ // We mimic failing series server, but practically context cancel will do the same.
283
+ testutil .NotOk (t , m .Series (& storepb.SeriesRequest {PartialResponseStrategy : storepb .PartialResponseStrategy_ABORT }, & mockedSeriesServer {
284
+ ctx : ctx ,
285
+ send : func (* storepb.SeriesResponse ) error {
286
+ cancel ()
287
+ return ctx .Err ()
288
+ },
289
+ }))
290
+ testutil .NotOk (t , ctx .Err ())
291
+ }); ! ok {
292
+ return
293
+ }
294
+ }
0 commit comments