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  }