TestAsyncInitRemoteConfigUpdates verifies that a database with in-progress async index initialization can accept config updates made on other nodes (arriving via polling) (prior to CBG-4008, operations would block waiting for async init to complete)
(t *testing.T)
| 740 | // index initialization can accept config updates made on other nodes (arriving via polling) |
| 741 | // (prior to CBG-4008, operations would block waiting for async init to complete) |
| 742 | func TestAsyncInitRemoteConfigUpdates(t *testing.T) { |
| 743 | if base.UnitTestUrlIsWalrus() { |
| 744 | t.Skip("This test only works against Couchbase Server") |
| 745 | } |
| 746 | base.TestRequiresCollections(t) |
| 747 | base.SetUpTestLogging(t, base.LevelDebug, base.KeyHTTP) |
| 748 | |
| 749 | // enable config polling to allow testing of cross-node updates |
| 750 | bootstrapConfig := rest.BootstrapStartupConfigForTest(t) |
| 751 | bootstrapConfig.Bootstrap.ConfigUpdateFrequency = base.NewConfigDuration(1 * time.Second) |
| 752 | sc, closeFn := rest.StartServerWithConfig(t, &bootstrapConfig) |
| 753 | defer closeFn() |
| 754 | |
| 755 | // Set testing callbacks for async initialization |
| 756 | collectionCount := int64(0) |
| 757 | initStarted := make(chan error) |
| 758 | unblockInit := make(chan error) |
| 759 | collectionCompleteCallback := func(_ string, _ base.ScopeAndCollectionName, status db.CollectionIndexStatus) { |
| 760 | if status != db.CollectionIndexStatusReady { |
| 761 | return |
| 762 | } |
| 763 | count := atomic.AddInt64(&collectionCount, 1) |
| 764 | // On first collection, close initStarted channel |
| 765 | log.Printf("collection callback count: %v", count) |
| 766 | if count == 1 { |
| 767 | log.Printf("closing initStarted") |
| 768 | close(initStarted) |
| 769 | } |
| 770 | rest.WaitForChannel(t, unblockInit, "waiting for test to unblock initialization") |
| 771 | } |
| 772 | sc.DatabaseInitManager.SetTestCallbacks(collectionCompleteCallback, nil) |
| 773 | |
| 774 | ctx := base.TestCtx(t) |
| 775 | // Get a test bucket, and use it to create the database. |
| 776 | tb := base.GetTestBucket(t) |
| 777 | defer tb.Close(ctx) |
| 778 | |
| 779 | importFilter := "function(doc) { return true }" |
| 780 | syncFunc := "function(doc){ channel(doc.channels); }" |
| 781 | |
| 782 | dbName := "db" |
| 783 | dbConfig := makeDbConfig(t, tb, syncFunc, importFilter) |
| 784 | dbConfig.Name = dbName |
| 785 | dbConfig.StartOffline = base.Ptr(true) |
| 786 | |
| 787 | keyspace := dbName |
| 788 | if len(dbConfig.Scopes) > 0 { |
| 789 | keyspaces := getRESTKeyspaces(dbName, dbConfig.Scopes) |
| 790 | keyspace = keyspaces[0] |
| 791 | } |
| 792 | |
| 793 | bucketName := tb.GetName() |
| 794 | groupID := sc.Config.Bootstrap.ConfigGroupID |
| 795 | |
| 796 | // Simulate creation of the database with offline=true on another node |
| 797 | version, err := rest.GenerateDatabaseConfigVersionID(ctx, "", &dbConfig) |
| 798 | require.NoError(t, err) |
| 799 | metadataID, err := sc.BootstrapContext.ComputeMetadataIDForDbConfig(ctx, &dbConfig) |
nothing calls this directly
no test coverage detected