Skip to content

Commit 7663600

Browse files
authored
CBG-4614 Add toggle for using separate principal indexes (#7499)
1 parent b217065 commit 7663600

File tree

11 files changed

+66
-108
lines changed

11 files changed

+66
-108
lines changed

db/database.go

Lines changed: 21 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ type DatabaseContextOptions struct {
175175
GroupID string
176176
JavascriptTimeout time.Duration // Max time the JS functions run for (ie. sync fn, import filter)
177177
UseLegacySyncDocsIndex bool
178-
Serverless bool // If running in serverless mode
179178
Scopes ScopesOptions
180179
MetadataStore base.DataStore // If set, use this location/connection for SG metadata storage - if not set, metadata is stored using the same location/connection as the bucket used for data storage.
181180
MetadataID string // MetadataID used for metadata storage
@@ -869,12 +868,9 @@ func (context *DatabaseContext) Authenticator(ctx context.Context) *auth.Authent
869868
return authenticator
870869
}
871870

872-
func (context *DatabaseContext) IsServerless() bool {
873-
return context.Options.Serverless
874-
}
875-
871+
// UseLegacySyncDocsIndex returns true there is an index over all docs starting with _sync, or if there are individual indexes for users and roles.
876872
func (context *DatabaseContext) UseLegacySyncDocsIndex() bool {
877-
return true // switch in CBG-4614
873+
return context.Options.UseLegacySyncDocsIndex
878874
}
879875

880876
// Makes a Database object given its name and bucket.
@@ -1013,60 +1009,31 @@ func (c *DatabaseCollection) processForEachDocIDResults(ctx context.Context, cal
10131009
// Returns the IDs of all users and roles, including deleted Roles
10141010
func (db *DatabaseContext) AllPrincipalIDs(ctx context.Context) (users, roles []string, err error) {
10151011

1016-
if !db.IsServerless() || db.Options.UseViews {
1012+
if db.UseLegacySyncDocsIndex() || db.Options.UseViews {
10171013
return db.getAllPrincipalIDsSyncDocs(ctx)
10181014
}
10191015

1020-
// If running in Serverless mode, we can leverage `users` and `roles` index
1021-
// to fetch users and roles
1022-
usersCh := db.getUserNamesInBackground(ctx)
1023-
rolesCh := db.getRoleIDsInBackground(ctx)
1024-
1025-
userData := <-usersCh
1026-
if userData.err != nil {
1027-
return nil, nil, userData.err
1028-
}
1029-
users = userData.value
1030-
1031-
rolesData := <-rolesCh
1032-
if rolesData.err != nil {
1033-
return nil, nil, rolesData.err
1034-
}
1035-
roles = rolesData.value
1036-
1037-
return users, roles, err
1038-
}
1039-
1040-
// used to send users/roles data from background fetch
1041-
type data struct {
1042-
value []string
1043-
err error
1044-
}
1045-
1046-
func (db *DatabaseContext) getUserNamesInBackground(ctx context.Context) <-chan data {
1047-
ch := make(chan data, 1)
1016+
wg := sync.WaitGroup{}
1017+
wg.Add(2)
1018+
var getUsersErr error
10481019
go func() {
1049-
defer close(ch)
1050-
users, err := db.GetUserNames(ctx)
1051-
ch <- data{
1052-
value: users,
1053-
err: err,
1054-
}
1020+
defer wg.Done()
1021+
users, getUsersErr = db.GetUserNames(ctx)
10551022
}()
1056-
return ch
1057-
}
1058-
1059-
func (db *DatabaseContext) getRoleIDsInBackground(ctx context.Context) <-chan data {
1060-
ch := make(chan data, 1)
1023+
var getRolesErr error
10611024
go func() {
1062-
defer close(ch)
1063-
roles, err := db.getRoleIDsUsingIndex(ctx, true)
1064-
ch <- data{
1065-
value: roles,
1066-
err: err,
1067-
}
1025+
defer wg.Done()
1026+
includeDeleted := true
1027+
roles, getRolesErr = db.getRoleIDsUsingIndex(ctx, includeDeleted)
10681028
}()
1069-
return ch
1029+
wg.Wait()
1030+
if getUsersErr != nil {
1031+
return nil, nil, getUsersErr
1032+
}
1033+
if getRolesErr != nil {
1034+
return nil, nil, getRolesErr
1035+
}
1036+
return users, roles, err
10701037
}
10711038

10721039
// Returns the Names of all users
@@ -1337,6 +1304,7 @@ outerLoop:
13371304
return users, nil
13381305
}
13391306

1307+
// getRoleIDsUsingIndex returns names of all roles. includDeleted toggles whether or not to include deleted roles.
13401308
func (db *DatabaseContext) getRoleIDsUsingIndex(ctx context.Context, includeDeleted bool) (roles []string, err error) {
13411309

13421310
dbRoleIDPrefix := db.MetadataKeys.RoleKeyPrefix()

db/database_test.go

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -431,30 +431,6 @@ func TestGetRemovedAsUser(t *testing.T) {
431431
assertHTTPError(t, err, 404)
432432
}
433433

434-
func TestIsServerless(t *testing.T) {
435-
testCases := []struct {
436-
title string
437-
serverless bool
438-
}{
439-
{
440-
serverless: true,
441-
},
442-
{
443-
serverless: false,
444-
},
445-
}
446-
447-
for _, testCase := range testCases {
448-
t.Run(fmt.Sprintf("TestIsServerless with Serverless=%t", testCase.serverless), func(t *testing.T) {
449-
db, ctx := setupTestDB(t)
450-
defer db.Close(ctx)
451-
452-
db.Options.Serverless = testCase.serverless
453-
assert.Equal(t, testCase.serverless, db.IsServerless())
454-
})
455-
}
456-
}
457-
458434
// Test removal handling for unavailable multi-channel revisions.
459435
func TestGetRemovalMultiChannel(t *testing.T) {
460436
db, ctx := setupTestDB(t)

db/indexes.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ var (
141141
IndexChannels: IdxFlagIndexTombstones,
142142
IndexAllDocs: IdxFlagIndexTombstones,
143143
IndexSyncDocs: IdxFlagMetadataOnly | IdxFlagPrincipalDocsOnly,
144-
IndexUser: IdxFlagMetadataOnly,
145-
IndexRole: IdxFlagMetadataOnly,
144+
IndexUser: IdxFlagMetadataOnly | IdxFlagPrincipalDocsOnly,
145+
IndexRole: IdxFlagMetadataOnly | IdxFlagPrincipalDocsOnly,
146146
IndexTombstones: IdxFlagXattrOnly | IdxFlagIndexTombstones,
147147
}
148148

@@ -261,7 +261,7 @@ func (i *SGIndex) isXattrOnly() bool {
261261
return i.flags&IdxFlagXattrOnly != 0
262262
}
263263

264-
// shouldCreate returns if given index should be created based on Serverless mode
264+
// shouldCreate returns if given index should be created.
265265
func (i *SGIndex) shouldCreate(options InitializeIndexOptions) bool {
266266
if options.LegacySyncDocsIndex {
267267
if i.creationMode == SeparatePrincipalIndexes {

db/indexes_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ func TestRemoveIndexesUseViewsTrueAndFalse(t *testing.T) {
232232
NumReplicas: 0,
233233
LegacySyncDocsIndex: db.UseLegacySyncDocsIndex(),
234234
UseXattrs: base.TestUseXattrs(),
235+
NumPartitions: DefaultNumIndexPartitions,
235236
}
236237
if db.OnlyDefaultCollection() {
237238
options.MetadataIndexes = IndexesAll

db/indextest/util.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ func getDatabaseContextOptions(useLegacySyncDocsIndex bool) db.DatabaseContextOp
2424
return db.DatabaseContextOptions{
2525
CacheOptions: &defaultCacheOptions,
2626
UseLegacySyncDocsIndex: useLegacySyncDocsIndex,
27-
Serverless: !useLegacySyncDocsIndex, // after CBG-4614, this flag will not be used
2827
}
2928
}
3029

db/query.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ func (context *DatabaseContext) QueryUsers(ctx context.Context, startKey string,
599599
// query is covering.
600600
func (context *DatabaseContext) BuildUsersQuery(startKey string, limit int) (string, map[string]interface{}) {
601601
var queryStatement string
602-
if context.IsServerless() {
602+
if !context.UseLegacySyncDocsIndex() {
603603
queryStatement = replaceIndexTokensQuery(QueryUsers.statement, sgIndexes[IndexUser], context.UseXattrs(), context.numIndexPartitions())
604604
} else {
605605
queryStatement = replaceIndexTokensQuery(QueryUsersUsingSyncDocsIdx.statement, sgIndexes[IndexSyncDocs], context.UseXattrs(), context.numIndexPartitions())
@@ -643,7 +643,7 @@ func (context *DatabaseContext) QueryRoles(ctx context.Context, startKey string,
643643
func (context *DatabaseContext) BuildRolesQuery(startKey string, limit int) (string, map[string]interface{}) {
644644

645645
var queryStatement string
646-
if context.IsServerless() {
646+
if !context.UseLegacySyncDocsIndex() {
647647
queryStatement = replaceIndexTokensQuery(QueryRolesExcludeDeletedUsingRoleIdx.statement, sgIndexes[IndexRole], context.UseXattrs(), context.numIndexPartitions())
648648
} else {
649649
queryStatement = replaceIndexTokensQuery(QueryRolesExcludeDeleted.statement, sgIndexes[IndexSyncDocs], context.UseXattrs(), context.numIndexPartitions())
@@ -668,7 +668,7 @@ func (context *DatabaseContext) QueryAllRoles(ctx context.Context, startKey stri
668668
}
669669

670670
var queryStatement string
671-
if context.IsServerless() {
671+
if !context.UseLegacySyncDocsIndex() {
672672
queryStatement = replaceIndexTokensQuery(QueryAllRolesUsingRoleIdx.statement, sgIndexes[IndexRole], context.UseXattrs(), context.numIndexPartitions())
673673
} else {
674674
queryStatement = replaceIndexTokensQuery(QueryAllRolesUsingSyncDocsIdx.statement, sgIndexes[IndexSyncDocs], context.UseXattrs(), context.numIndexPartitions())

db/util_testing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ var viewsAndGSIBucketInit base.TBPBucketInitFunc = func(ctx context.Context, b b
375375
UseXattrs: base.TestUseXattrs(),
376376
NumReplicas: 0,
377377
WaitForIndexesOnlineOption: base.WaitForIndexesDefault,
378-
LegacySyncDocsIndex: true, // Change in CBG-4614
378+
LegacySyncDocsIndex: false,
379379
MetadataIndexes: IndexesWithoutMetadata,
380380
NumPartitions: DefaultNumIndexPartitions,
381381
}

rest/database_init_manager_test.go

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"github.com/stretchr/testify/require"
2323
)
2424

25+
const testUseLegacySyncDocsIndex = false
26+
2527
func TestDatabaseInitManager(t *testing.T) {
2628
RequireN1QLIndexes(t)
2729

@@ -45,9 +47,8 @@ func TestDatabaseInitManager(t *testing.T) {
4547
// Drop indexes
4648
dropAllNonPrimaryIndexes(t, tb.GetSingleDataStore())
4749

48-
useLegacySyncDocsIndex := true // flip in CBG-4615
4950
// Async index creation
50-
doneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
51+
doneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
5152
require.NoError(t, err)
5253

5354
select {
@@ -111,16 +112,15 @@ func TestDatabaseInitConfigChangeSameCollections(t *testing.T) {
111112
dbConfig := makeDbConfig(tb.GetName(), dbName, collection1and2ScopesConfig)
112113
require.NoError(t, dbConfig.setup(ctx, dbName, sc.Config.Bootstrap, nil, nil, false))
113114

114-
useLegacySyncDocsIndex := true // flip in CBG-4615
115115
// Start first async index creation, blocks after first collection
116-
doneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
116+
doneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
117117
require.NoError(t, err)
118118

119119
// Wait for first collection to be initialized
120120
WaitForChannel(t, singleCollectionInitChannel, "first collection init")
121121

122122
// Make a duplicate call to initialize database, should reuse the existing agent
123-
duplicateDoneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
123+
duplicateDoneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
124124
require.NoError(t, err)
125125

126126
// Unblock collection callback to process all remaining collections
@@ -137,7 +137,7 @@ func TestDatabaseInitConfigChangeSameCollections(t *testing.T) {
137137
waitForWorkerDone(t, initMgr, "dbName")
138138

139139
// Rerun init, should start a new worker for the database and re-verify init for each collection
140-
rerunDoneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
140+
rerunDoneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
141141
require.NoError(t, err)
142142
WaitForChannel(t, rerunDoneChan, "repeated init done chan")
143143
totalCount = atomic.LoadInt64(&collectionCount)
@@ -201,9 +201,8 @@ func TestDatabaseInitConfigChangeDifferentCollections(t *testing.T) {
201201
dbConfig := makeDbConfig(tb.GetName(), dbName, collection1and2ScopesConfig)
202202
require.NoError(t, dbConfig.setup(ctx, dbName, sc.Config.Bootstrap, nil, nil, false))
203203

204-
useLegacySyncDocsIndex := true // flip in CBG-4615
205204
// Start first async index creation, should block after first collection
206-
doneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
205+
doneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
207206
require.NoError(t, err)
208207

209208
// Wait for first collection to be initialized
@@ -212,7 +211,7 @@ func TestDatabaseInitConfigChangeDifferentCollections(t *testing.T) {
212211
// Make a call to initialize database for the same db name, different collections
213212
modifiedDbConfig := makeDbConfig(tb.GetName(), dbName, collection1and3ScopesConfig)
214213
require.NoError(t, modifiedDbConfig.setup(ctx, dbName, sc.Config.Bootstrap, nil, nil, false))
215-
modifiedDoneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, modifiedDbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
214+
modifiedDoneChan, err := initMgr.InitializeDatabase(ctx, sc.Config, modifiedDbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
216215
require.NoError(t, err)
217216

218217
// Unblock the first InitializeDatabase, should cancel
@@ -292,16 +291,15 @@ func TestDatabaseInitConcurrentDatabasesSameBucket(t *testing.T) {
292291
db2Config := makeDbConfig(tb.GetName(), db2Name, collection3ScopesConfig)
293292
require.NoError(t, db2Config.setup(ctx, db2Name, sc.Config.Bootstrap, nil, nil, false))
294293

295-
useLegacySyncDocsIndex := true // flip in CBG-4615
296294
// Start first async index creation, should block after first collection
297-
doneChan1, err := initMgr.InitializeDatabase(ctx, sc.Config, db1Config.ToDatabaseConfig(), useLegacySyncDocsIndex)
295+
doneChan1, err := initMgr.InitializeDatabase(ctx, sc.Config, db1Config.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
298296
require.NoError(t, err)
299297

300298
// Wait for first collection to be initialized
301299
WaitForChannel(t, firstCollectionInitChannel, "first collection init")
302300

303301
// Start second async index creation for db2 while first is still running
304-
doneChan2, err := initMgr.InitializeDatabase(ctx, sc.Config, db2Config.ToDatabaseConfig(), useLegacySyncDocsIndex)
302+
doneChan2, err := initMgr.InitializeDatabase(ctx, sc.Config, db2Config.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
305303
require.NoError(t, err)
306304

307305
// Unblock the first InitializeDatabase, should cancel
@@ -386,16 +384,15 @@ func TestDatabaseInitConcurrentDatabasesDifferentBuckets(t *testing.T) {
386384
db2Config := makeDbConfig(tb2.GetName(), db2Name, collection1and2ScopesConfig)
387385
require.NoError(t, db2Config.setup(ctx, db2Name, sc.Config.Bootstrap, nil, nil, false))
388386

389-
useLegacySyncDocsIndex := true // flip in CBG-4615
390387
// Start first async index creation, should block after first collection
391-
doneChan1, err := initMgr.InitializeDatabase(ctx, sc.Config, db1Config.ToDatabaseConfig(), useLegacySyncDocsIndex)
388+
doneChan1, err := initMgr.InitializeDatabase(ctx, sc.Config, db1Config.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
392389
require.NoError(t, err)
393390

394391
// Wait for first collection to be initialized
395392
WaitForChannel(t, firstCollectionInitChannel, "first collection init")
396393

397394
// Start second async index creation for db2 while first is still running
398-
doneChan2, err := initMgr.InitializeDatabase(ctx, sc.Config, db2Config.ToDatabaseConfig(), useLegacySyncDocsIndex)
395+
doneChan2, err := initMgr.InitializeDatabase(ctx, sc.Config, db2Config.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
399396
require.NoError(t, err)
400397

401398
// Unblock the first InitializeDatabase, should cancel
@@ -456,7 +453,6 @@ func TestDatabaseInitTeardownTiming(t *testing.T) {
456453
dbName := "dbName"
457454
dbConfig := makeDbConfig(tb.GetName(), dbName, collection1and2ScopesConfig)
458455
require.NoError(t, dbConfig.setup(ctx, dbName, sc.Config.Bootstrap, nil, nil, false))
459-
useLegacySyncDocsIndex := true // flip in CBG-4615
460456

461457
wg := &sync.WaitGroup{}
462458
wg.Add(1)
@@ -467,7 +463,7 @@ func TestDatabaseInitTeardownTiming(t *testing.T) {
467463
if currentCount == 0 {
468464
defer wg.Done()
469465
log.Printf("invoking InitializeDatabase again during teardown")
470-
doneChan2, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
466+
doneChan2, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
471467
require.NoError(t, err)
472468
WaitForChannel(t, doneChan2, "done chan 2")
473469
}
@@ -476,7 +472,7 @@ func TestDatabaseInitTeardownTiming(t *testing.T) {
476472
}
477473

478474
// Start first async index creation, should block after first collection
479-
doneChan1, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), useLegacySyncDocsIndex)
475+
doneChan1, err := initMgr.InitializeDatabase(ctx, sc.Config, dbConfig.ToDatabaseConfig(), testUseLegacySyncDocsIndex)
480476
require.NoError(t, err)
481477

482478
WaitForChannel(t, doneChan1, "done chan 1")

rest/indextest/index_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,33 @@ func TestSyncGatewayStartupIndexes(t *testing.T) {
6262
// use example indexes to make sure metadata and non metadata are created
6363
indexSyncDocs := "sg_syncDocs"
6464
indexAccess := "sg_access"
65+
indexRoles := "sg_roles"
66+
indexUsers := "sg_users"
6567
if base.TestUseXattrs() {
6668
indexSyncDocs += "_x1"
6769
indexAccess += "_x1"
70+
indexRoles += "_x1"
71+
indexUsers += "_x1"
6872
} else {
6973
indexSyncDocs += "_1"
7074
indexAccess += "_1"
75+
indexRoles += "_1"
76+
indexUsers += "_1"
7177
}
7278
metadataCollection, err := base.AsCollection(bucket.DefaultDataStore())
7379
require.NoError(t, err)
7480
indexNames, err := metadataCollection.GetIndexes()
7581
require.NoError(t, err)
7682

77-
require.Contains(t, indexNames, indexSyncDocs)
83+
if rt.GetDatabase().UseLegacySyncDocsIndex() {
84+
require.Contains(t, indexNames, indexSyncDocs)
85+
require.NotContains(t, indexNames, indexRoles)
86+
require.NotContains(t, indexNames, indexUsers)
87+
} else {
88+
require.NotContains(t, indexNames, indexSyncDocs)
89+
require.Contains(t, indexNames, indexRoles)
90+
require.Contains(t, indexNames, indexUsers)
91+
}
7892

7993
if base.TestsUseNamedCollections() {
8094
require.NotContains(t, indexNames, indexAccess)

0 commit comments

Comments
 (0)