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