github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/storage/tsdb/users_scanner.go (about) 1 package tsdb 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/go-kit/log" 8 "github.com/go-kit/log/level" 9 "github.com/thanos-io/thanos/pkg/objstore" 10 ) 11 12 // AllUsers returns true to each call and should be used whenever the UsersScanner should not filter out 13 // any user due to sharding. 14 func AllUsers(_ string) (bool, error) { 15 return true, nil 16 } 17 18 type UsersScanner struct { 19 bucketClient objstore.Bucket 20 logger log.Logger 21 isOwned func(userID string) (bool, error) 22 } 23 24 func NewUsersScanner(bucketClient objstore.Bucket, isOwned func(userID string) (bool, error), logger log.Logger) *UsersScanner { 25 return &UsersScanner{ 26 bucketClient: bucketClient, 27 logger: logger, 28 isOwned: isOwned, 29 } 30 } 31 32 // ScanUsers returns a fresh list of users found in the storage, that are not marked for deletion, 33 // and list of users marked for deletion. 34 // 35 // If sharding is enabled, returned lists contains only the users owned by this instance. 36 func (s *UsersScanner) ScanUsers(ctx context.Context) (users, markedForDeletion []string, err error) { 37 err = s.bucketClient.Iter(ctx, "", func(entry string) error { 38 users = append(users, strings.TrimSuffix(entry, "/")) 39 return nil 40 }) 41 if err != nil { 42 return nil, nil, err 43 } 44 45 // Check users for being owned by instance, and split users into non-deleted and deleted. 46 // We do these checks after listing all users, to improve cacheability of Iter (result is only cached at the end of Iter call). 47 for ix := 0; ix < len(users); { 48 userID := users[ix] 49 50 // Check if it's owned by this instance. 51 owned, err := s.isOwned(userID) 52 if err != nil { 53 level.Warn(s.logger).Log("msg", "unable to check if user is owned by this shard", "user", userID, "err", err) 54 } else if !owned { 55 users = append(users[:ix], users[ix+1:]...) 56 continue 57 } 58 59 deletionMarkExists, err := TenantDeletionMarkExists(ctx, s.bucketClient, userID) 60 if err != nil { 61 level.Warn(s.logger).Log("msg", "unable to check if user is marked for deletion", "user", userID, "err", err) 62 } else if deletionMarkExists { 63 users = append(users[:ix], users[ix+1:]...) 64 markedForDeletion = append(markedForDeletion, userID) 65 continue 66 } 67 68 ix++ 69 } 70 71 return users, markedForDeletion, nil 72 }