@@ -44,8 +44,15 @@ import (
44
44
"github.com/cortexproject/cortex/pkg/util/validation"
45
45
)
46
46
47
- // BucketStores is a multi-tenant wrapper of Thanos BucketStore.
48
- type BucketStores struct {
47
+ // BucketStores defines the methods that any bucket stores implementation must provide
48
+ type BucketStores interface {
49
+ storepb.StoreServer
50
+ SyncBlocks (ctx context.Context ) error
51
+ InitialSync (ctx context.Context ) error
52
+ }
53
+
54
+ // ThanosBucketStores is a multi-tenant wrapper of Thanos BucketStore.
55
+ type ThanosBucketStores struct {
49
56
logger log.Logger
50
57
cfg tsdb.BlocksStorageConfig
51
58
limits * validation.Overrides
@@ -74,7 +81,7 @@ type BucketStores struct {
74
81
storesMu sync.RWMutex
75
82
stores map [string ]* store.BucketStore
76
83
77
- // Keeps the last sync error for the bucket store for each tenant.
84
+ // Keeps the last sync error for the bucket store for each tenant.
78
85
storesErrorsMu sync.RWMutex
79
86
storesErrors map [string ]error
80
87
@@ -86,8 +93,7 @@ type BucketStores struct {
86
93
userScanner users.Scanner
87
94
88
95
// Keeps number of inflight requests
89
- inflightRequestCnt int
90
- inflightRequestMu sync.RWMutex
96
+ inflightRequests * util.InflightRequestTracker
91
97
92
98
// Metrics.
93
99
syncTimes prometheus.Histogram
@@ -99,7 +105,19 @@ type BucketStores struct {
99
105
var ErrTooManyInflightRequests = status .Error (codes .ResourceExhausted , "too many inflight requests in store gateway" )
100
106
101
107
// NewBucketStores makes a new BucketStores.
102
- func NewBucketStores (cfg tsdb.BlocksStorageConfig , shardingStrategy ShardingStrategy , bucketClient objstore.InstrumentedBucket , limits * validation.Overrides , logLevel logging.Level , logger log.Logger , reg prometheus.Registerer ) (* BucketStores , error ) {
108
+ func NewBucketStores (cfg tsdb.BlocksStorageConfig , shardingStrategy ShardingStrategy , bucketClient objstore.InstrumentedBucket , limits * validation.Overrides , logLevel logging.Level , logger log.Logger , reg prometheus.Registerer ) (BucketStores , error ) {
109
+ switch cfg .BucketStore .BucketStoreType {
110
+ case string (tsdb .ParquetBucketStore ):
111
+ return newParquetBucketStores (cfg , bucketClient , limits , logger , reg )
112
+ case string (tsdb .TSDBBucketStore ):
113
+ return newThanosBucketStores (cfg , shardingStrategy , bucketClient , limits , logLevel , logger , reg )
114
+ default :
115
+ return nil , fmt .Errorf ("unsupported bucket store type: %s" , cfg .BucketStore .BucketStoreType )
116
+ }
117
+ }
118
+
119
+ // newThanosBucketStores creates a new TSDB-based bucket stores
120
+ func newThanosBucketStores (cfg tsdb.BlocksStorageConfig , shardingStrategy ShardingStrategy , bucketClient objstore.InstrumentedBucket , limits * validation.Overrides , logLevel logging.Level , logger log.Logger , reg prometheus.Registerer ) (* ThanosBucketStores , error ) {
103
121
matchers := tsdb .NewMatchers ()
104
122
cachingBucket , err := tsdb .CreateCachingBucket (cfg .BucketStore .ChunksCache , cfg .BucketStore .MetadataCache , tsdb.ParquetLabelsCacheConfig {}, matchers , bucketClient , logger , reg )
105
123
if err != nil {
@@ -114,7 +132,7 @@ func NewBucketStores(cfg tsdb.BlocksStorageConfig, shardingStrategy ShardingStra
114
132
Help : "Number of maximum concurrent queries allowed." ,
115
133
}).Set (float64 (cfg .BucketStore .MaxConcurrent ))
116
134
117
- u := & BucketStores {
135
+ u := & ThanosBucketStores {
118
136
logger : logger ,
119
137
cfg : cfg ,
120
138
limits : limits ,
@@ -128,6 +146,7 @@ func NewBucketStores(cfg tsdb.BlocksStorageConfig, shardingStrategy ShardingStra
128
146
queryGate : queryGate ,
129
147
partitioner : newGapBasedPartitioner (cfg .BucketStore .PartitionerMaxGapBytes , reg ),
130
148
userTokenBuckets : make (map [string ]* util.TokenBucket ),
149
+ inflightRequests : util .NewInflightRequestTracker (),
131
150
syncTimes : promauto .With (reg ).NewHistogram (prometheus.HistogramOpts {
132
151
Name : "cortex_bucket_stores_blocks_sync_seconds" ,
133
152
Help : "The total time it takes to perform a sync stores" ,
@@ -187,7 +206,7 @@ func NewBucketStores(cfg tsdb.BlocksStorageConfig, shardingStrategy ShardingStra
187
206
}
188
207
189
208
// InitialSync does an initial synchronization of blocks for all users.
190
- func (u * BucketStores ) InitialSync (ctx context.Context ) error {
209
+ func (u * ThanosBucketStores ) InitialSync (ctx context.Context ) error {
191
210
level .Info (u .logger ).Log ("msg" , "synchronizing TSDB blocks for all users" )
192
211
193
212
if err := u .syncUsersBlocksWithRetries (ctx , func (ctx context.Context , s * store.BucketStore ) error {
@@ -202,13 +221,13 @@ func (u *BucketStores) InitialSync(ctx context.Context) error {
202
221
}
203
222
204
223
// SyncBlocks synchronizes the stores state with the Bucket store for every user.
205
- func (u * BucketStores ) SyncBlocks (ctx context.Context ) error {
224
+ func (u * ThanosBucketStores ) SyncBlocks (ctx context.Context ) error {
206
225
return u .syncUsersBlocksWithRetries (ctx , func (ctx context.Context , s * store.BucketStore ) error {
207
226
return s .SyncBlocks (ctx )
208
227
})
209
228
}
210
229
211
- func (u * BucketStores ) syncUsersBlocksWithRetries (ctx context.Context , f func (context.Context , * store.BucketStore ) error ) error {
230
+ func (u * ThanosBucketStores ) syncUsersBlocksWithRetries (ctx context.Context , f func (context.Context , * store.BucketStore ) error ) error {
212
231
retries := backoff .New (ctx , backoff.Config {
213
232
MinBackoff : 1 * time .Second ,
214
233
MaxBackoff : 10 * time .Second ,
@@ -232,7 +251,7 @@ func (u *BucketStores) syncUsersBlocksWithRetries(ctx context.Context, f func(co
232
251
return lastErr
233
252
}
234
253
235
- func (u * BucketStores ) syncUsersBlocks (ctx context.Context , f func (context.Context , * store.BucketStore ) error ) (returnErr error ) {
254
+ func (u * ThanosBucketStores ) syncUsersBlocks (ctx context.Context , f func (context.Context , * store.BucketStore ) error ) (returnErr error ) {
236
255
defer func (start time.Time ) {
237
256
u .syncTimes .Observe (time .Since (start ).Seconds ())
238
257
if returnErr == nil {
@@ -330,7 +349,7 @@ func (u *BucketStores) syncUsersBlocks(ctx context.Context, f func(context.Conte
330
349
}
331
350
332
351
// Series makes a series request to the underlying user bucket store.
333
- func (u * BucketStores ) Series (req * storepb.SeriesRequest , srv storepb.Store_SeriesServer ) error {
352
+ func (u * ThanosBucketStores ) Series (req * storepb.SeriesRequest , srv storepb.Store_SeriesServer ) error {
334
353
spanLog , spanCtx := spanlogger .New (srv .Context (), "BucketStores.Series" )
335
354
defer spanLog .Finish ()
336
355
@@ -356,12 +375,12 @@ func (u *BucketStores) Series(req *storepb.SeriesRequest, srv storepb.Store_Seri
356
375
357
376
maxInflightRequests := u .cfg .BucketStore .MaxInflightRequests
358
377
if maxInflightRequests > 0 {
359
- if u .getInflightRequestCnt () >= maxInflightRequests {
378
+ if u .inflightRequests . Count () >= maxInflightRequests {
360
379
return ErrTooManyInflightRequests
361
380
}
362
381
363
- u .incrementInflightRequestCnt ()
364
- defer u .decrementInflightRequestCnt ()
382
+ u .inflightRequests . Inc ()
383
+ defer u .inflightRequests . Dec ()
365
384
}
366
385
367
386
err = store .Series (req , spanSeriesServer {
@@ -372,26 +391,8 @@ func (u *BucketStores) Series(req *storepb.SeriesRequest, srv storepb.Store_Seri
372
391
return err
373
392
}
374
393
375
- func (u * BucketStores ) getInflightRequestCnt () int {
376
- u .inflightRequestMu .RLock ()
377
- defer u .inflightRequestMu .RUnlock ()
378
- return u .inflightRequestCnt
379
- }
380
-
381
- func (u * BucketStores ) incrementInflightRequestCnt () {
382
- u .inflightRequestMu .Lock ()
383
- u .inflightRequestCnt ++
384
- u .inflightRequestMu .Unlock ()
385
- }
386
-
387
- func (u * BucketStores ) decrementInflightRequestCnt () {
388
- u .inflightRequestMu .Lock ()
389
- u .inflightRequestCnt --
390
- u .inflightRequestMu .Unlock ()
391
- }
392
-
393
394
// LabelNames implements the Storegateway proto service.
394
- func (u * BucketStores ) LabelNames (ctx context.Context , req * storepb.LabelNamesRequest ) (* storepb.LabelNamesResponse , error ) {
395
+ func (u * ThanosBucketStores ) LabelNames (ctx context.Context , req * storepb.LabelNamesRequest ) (* storepb.LabelNamesResponse , error ) {
395
396
spanLog , spanCtx := spanlogger .New (ctx , "BucketStores.LabelNames" )
396
397
defer spanLog .Finish ()
397
398
@@ -421,7 +422,7 @@ func (u *BucketStores) LabelNames(ctx context.Context, req *storepb.LabelNamesRe
421
422
}
422
423
423
424
// LabelValues implements the Storegateway proto service.
424
- func (u * BucketStores ) LabelValues (ctx context.Context , req * storepb.LabelValuesRequest ) (* storepb.LabelValuesResponse , error ) {
425
+ func (u * ThanosBucketStores ) LabelValues (ctx context.Context , req * storepb.LabelValuesRequest ) (* storepb.LabelValuesResponse , error ) {
425
426
spanLog , spanCtx := spanlogger .New (ctx , "BucketStores.LabelValues" )
426
427
defer spanLog .Finish ()
427
428
@@ -450,7 +451,7 @@ func (u *BucketStores) LabelValues(ctx context.Context, req *storepb.LabelValues
450
451
451
452
// scanUsers in the bucket and return the list of found users. It includes active and deleting users
452
453
// but not deleted users.
453
- func (u * BucketStores ) scanUsers (ctx context.Context ) ([]string , error ) {
454
+ func (u * ThanosBucketStores ) scanUsers (ctx context.Context ) ([]string , error ) {
454
455
activeUsers , deletingUsers , _ , err := u .userScanner .ScanUsers (ctx )
455
456
if err != nil {
456
457
return nil , err
@@ -477,13 +478,13 @@ func deduplicateUsers(users []string) []string {
477
478
return uniqueUsers
478
479
}
479
480
480
- func (u * BucketStores ) getStore (userID string ) * store.BucketStore {
481
+ func (u * ThanosBucketStores ) getStore (userID string ) * store.BucketStore {
481
482
u .storesMu .RLock ()
482
483
defer u .storesMu .RUnlock ()
483
484
return u .stores [userID ]
484
485
}
485
486
486
- func (u * BucketStores ) getStoreError (userID string ) error {
487
+ func (u * ThanosBucketStores ) getStoreError (userID string ) error {
487
488
u .storesErrorsMu .RLock ()
488
489
defer u .storesErrorsMu .RUnlock ()
489
490
return u .storesErrors [userID ]
@@ -499,7 +500,7 @@ var (
499
500
// If bucket store doesn't exist, returns errBucketStoreNotFound.
500
501
// If bucket store is not empty, returns errBucketStoreNotEmpty.
501
502
// Otherwise returns error from closing the bucket store.
502
- func (u * BucketStores ) closeEmptyBucketStore (userID string ) error {
503
+ func (u * ThanosBucketStores ) closeEmptyBucketStore (userID string ) error {
503
504
u .storesMu .Lock ()
504
505
unlockInDefer := true
505
506
defer func () {
@@ -537,11 +538,11 @@ func isEmptyBucketStore(bs *store.BucketStore) bool {
537
538
return min == math .MaxInt64 && max == math .MinInt64
538
539
}
539
540
540
- func (u * BucketStores ) syncDirForUser (userID string ) string {
541
+ func (u * ThanosBucketStores ) syncDirForUser (userID string ) string {
541
542
return filepath .Join (u .cfg .BucketStore .SyncDir , userID )
542
543
}
543
544
544
- func (u * BucketStores ) getOrCreateStore (userID string ) (* store.BucketStore , error ) {
545
+ func (u * ThanosBucketStores ) getOrCreateStore (userID string ) (* store.BucketStore , error ) {
545
546
// Check if the store already exists.
546
547
bs := u .getStore (userID )
547
548
if bs != nil {
@@ -721,7 +722,7 @@ func (u *BucketStores) getOrCreateStore(userID string) (*store.BucketStore, erro
721
722
722
723
// deleteLocalFilesForExcludedTenants removes local "sync" directories for tenants that are not included in the current
723
724
// shard.
724
- func (u * BucketStores ) deleteLocalFilesForExcludedTenants (includeUserIDs map [string ]struct {}) {
725
+ func (u * ThanosBucketStores ) deleteLocalFilesForExcludedTenants (includeUserIDs map [string ]struct {}) {
725
726
files , err := os .ReadDir (u .cfg .BucketStore .SyncDir )
726
727
if err != nil {
727
728
return
@@ -760,13 +761,13 @@ func (u *BucketStores) deleteLocalFilesForExcludedTenants(includeUserIDs map[str
760
761
}
761
762
}
762
763
763
- func (u * BucketStores ) getUserTokenBucket (userID string ) * util.TokenBucket {
764
+ func (u * ThanosBucketStores ) getUserTokenBucket (userID string ) * util.TokenBucket {
764
765
u .userTokenBucketsMu .RLock ()
765
766
defer u .userTokenBucketsMu .RUnlock ()
766
767
return u .userTokenBuckets [userID ]
767
768
}
768
769
769
- func (u * BucketStores ) getTokensToRetrieve (tokens uint64 , dataType store.StoreDataType ) int64 {
770
+ func (u * ThanosBucketStores ) getTokensToRetrieve (tokens uint64 , dataType store.StoreDataType ) int64 {
770
771
tokensToRetrieve := float64 (tokens )
771
772
switch dataType {
772
773
case store .PostingsFetched :
0 commit comments