-
Notifications
You must be signed in to change notification settings - Fork 544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shuffle User Order in UsersScanner #10513
Changes from 11 commits
cb1ff9a
98ab283
3fb093e
53a7aa9
803b53f
563bec7
53a55d9
61687ea
c511896
b39115f
d55ac40
3de014c
f9cab59
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ package tsdb | |
|
||
import ( | ||
"context" | ||
"math/rand" | ||
"strings" | ||
|
||
"github.com/go-kit/log" | ||
|
@@ -46,6 +47,10 @@ func (s *UsersScanner) ScanUsers(ctx context.Context) (users, markedForDeletion | |
return nil, nil, err | ||
} | ||
|
||
rand.Shuffle(len(users), func(i, j int) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know we've changed course on this a time or two, but |
||
users[i], users[j] = users[j], users[i] | ||
}) | ||
|
||
// 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); { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ package tsdb | |
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"path" | ||
"testing" | ||
|
||
|
@@ -36,10 +37,10 @@ func TestUsersScanner_ScanUsers_ShouldReturnedOwnedUsersOnly(t *testing.T) { | |
} | ||
|
||
func TestUsersScanner_ScanUsers_ShouldReturnUsersForWhichOwnerCheckOrTenantDeletionCheckFailed(t *testing.T) { | ||
expected := []string{"user-1", "user-2"} | ||
users := []string{"user-1", "user-2"} | ||
|
||
bucketClient := &bucket.ClientMock{} | ||
bucketClient.MockIter("", expected, nil) | ||
bucketClient.MockIter("", users, nil) | ||
bucketClient.MockExists(path.Join("user-1", TenantDeletionMarkPath), false, nil) | ||
bucketClient.MockExists(path.Join("user-2", TenantDeletionMarkPath), false, errors.New("fail")) | ||
|
||
|
@@ -50,11 +51,14 @@ func TestUsersScanner_ScanUsers_ShouldReturnUsersForWhichOwnerCheckOrTenantDelet | |
s := NewUsersScanner(bucketClient, isOwned, log.NewNopLogger()) | ||
actual, deleted, err := s.ScanUsers(context.Background()) | ||
require.NoError(t, err) | ||
assert.Equal(t, expected, actual) | ||
dmwilson-grafana marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for _, userID := range users { | ||
assert.Contains(t, actual, userID) | ||
} | ||
assert.Empty(t, deleted) | ||
} | ||
|
||
func TestUsersScanner_ScanUsers_ShouldNotReturnPrefixedUsedByMimirInternals(t *testing.T) { | ||
users := []string{"user-1", "user-2"} | ||
bucketClient := &bucket.ClientMock{} | ||
bucketClient.MockIter("", []string{"user-1", "user-2", bucket.MimirInternalsPrefix}, nil) | ||
bucketClient.MockExists(path.Join("user-1", TenantDeletionMarkPath), false, nil) | ||
|
@@ -63,5 +67,32 @@ func TestUsersScanner_ScanUsers_ShouldNotReturnPrefixedUsedByMimirInternals(t *t | |
s := NewUsersScanner(bucketClient, AllUsers, log.NewNopLogger()) | ||
actual, _, err := s.ScanUsers(context.Background()) | ||
require.NoError(t, err) | ||
assert.Equal(t, []string{"user-1", "user-2"}, actual) | ||
for _, userID := range users { | ||
assert.Contains(t, actual, userID) | ||
} | ||
} | ||
|
||
func TestUsersScanner_ScanUsers_ShouldReturnRandomizedOrder(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what this test is testing. It doesn't seem like it's ensuring a random order. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without the shuffle, the order of the input ( A better test might involve setting a specific rand.Source and checking that it shuffles to a specific order. |
||
var users = make([]string, 20) | ||
for i := 0; i < len(users); i++ { | ||
users[i] = fmt.Sprintf("user-%d", i) | ||
} | ||
bucketClient := &bucket.ClientMock{} | ||
bucketClient.MockIter("", users, nil) | ||
for i := 0; i < len(users); i++ { | ||
bucketClient.MockExists(path.Join(users[i], TenantDeletionMarkPath), false, nil) | ||
} | ||
|
||
isOwned := func(_ string) (bool, error) { | ||
return true, nil | ||
} | ||
|
||
s := NewUsersScanner(bucketClient, isOwned, log.NewNopLogger()) | ||
actual, deleted, err := s.ScanUsers(context.Background()) | ||
require.NoError(t, err) | ||
for _, userID := range users { | ||
assert.Contains(t, actual, userID) | ||
} | ||
assert.Empty(t, deleted) | ||
assert.NotEqual(t, actual, users) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this briefly say "why" in addition to "how"? So that unfamiliar readers understand why they might upgrade, and so on. :)