From 588f23b46208ee9c91215755bdf329d99e3bda5b Mon Sep 17 00:00:00 2001 From: Tor Colvin Date: Thu, 21 Dec 2023 11:32:16 -0500 Subject: [PATCH 1/4] Show documents that might be around after N1QL emptying fails --- db/util_testing.go | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/db/util_testing.go b/db/util_testing.go index 337e52e6f4..6cd2ab5149 100644 --- a/db/util_testing.go +++ b/db/util_testing.go @@ -44,14 +44,34 @@ func WaitForPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) error { retryWorker, base.CreateMaxDoublingSleeperFunc(60, 500, 5000), ) + var retryError *base.RetryTimeoutError + if errors.As(err, &retryError) { + files, err := getPrimaryIndexFiles(ctx, store, 0) + if err != nil { + return fmt.Errorf("Error getting files from primary index: %w", err) + } + return fmt.Errorf("Files left behind after waiting for primary index to be emptied: %s", files) + } return err - } -// isPrimaryIndexEmpty returs true if there are no documents in the primary index +// isPrimaryIndexEmpty returns true if there are no documents in the primary index func isPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) (bool, error) { + // only look for a single file to make query faster + docs, err := getPrimaryIndexFiles(ctx, store, 1) + if err != nil { + return false, err + } + return len(docs) == 0, err +} + +// getPrimaryIndexFiles returs true if there are no documents in the primary index +func getPrimaryIndexFiles(ctx context.Context, store base.N1QLStore, numFiles int) ([]string, error) { // Create the star channel query - statement := fmt.Sprintf("SELECT * FROM %s LIMIT 1", base.KeyspaceQueryToken) + statement := fmt.Sprintf("SELECT META().id FROM %s", base.KeyspaceQueryToken) + if numFiles != 0 { + statement += " LIMIT 1" + } params := map[string]interface{}{} params[QueryParamStartSeq] = 0 params[QueryParamEndSeq] = N1QLMaxInt64 @@ -62,18 +82,19 @@ func isPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) (bool, error // If there was an error, then retry. Assume it's an "index rollback" error which happens as // the index processes the bucket flush operation if err != nil { - return false, err + return nil, err } - // If it's empty, we're done - var queryRow map[string]interface{} - found := results.Next(ctx, &queryRow) + var documents []string + var queryRow map[string]string + for results.Next(ctx, &queryRow) { + documents = append(documents, queryRow["id"]) + } resultsCloseErr := results.Close() if resultsCloseErr != nil { - return false, err + return documents, err } - - return !found, nil + return documents, nil } func (db *DatabaseContext) CacheCompactActive() bool { From 7a24c4d8c0e4d8ad19ed0561153937afcc79ed2b Mon Sep 17 00:00:00 2001 From: Tor Colvin Date: Tue, 2 Jan 2024 10:48:14 -0500 Subject: [PATCH 2/4] Rename files to documents --- db/util_testing.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/db/util_testing.go b/db/util_testing.go index 6cd2ab5149..a909d0077a 100644 --- a/db/util_testing.go +++ b/db/util_testing.go @@ -46,11 +46,11 @@ func WaitForPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) error { ) var retryError *base.RetryTimeoutError if errors.As(err, &retryError) { - files, err := getPrimaryIndexFiles(ctx, store, 0) + files, err := getPrimaryIndexDocuments(ctx, store, true) if err != nil { return fmt.Errorf("Error getting files from primary index: %w", err) } - return fmt.Errorf("Files left behind after waiting for primary index to be emptied: %s", files) + return fmt.Errorf("Documents left behind after waiting for primary index to be emptied: %s", files) } return err } @@ -58,18 +58,18 @@ func WaitForPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) error { // isPrimaryIndexEmpty returns true if there are no documents in the primary index func isPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) (bool, error) { // only look for a single file to make query faster - docs, err := getPrimaryIndexFiles(ctx, store, 1) + docs, err := getPrimaryIndexDocuments(ctx, store, false) if err != nil { return false, err } return len(docs) == 0, err } -// getPrimaryIndexFiles returs true if there are no documents in the primary index -func getPrimaryIndexFiles(ctx context.Context, store base.N1QLStore, numFiles int) ([]string, error) { +// getPrimaryIndexDocuments returs true if there are no documents in the primary index +func getPrimaryIndexDocuments(ctx context.Context, store base.N1QLStore, allDocuments bool) ([]string, error) { // Create the star channel query statement := fmt.Sprintf("SELECT META().id FROM %s", base.KeyspaceQueryToken) - if numFiles != 0 { + if !allDocuments { statement += " LIMIT 1" } params := map[string]interface{}{} @@ -90,11 +90,8 @@ func getPrimaryIndexFiles(ctx context.Context, store base.N1QLStore, numFiles in for results.Next(ctx, &queryRow) { documents = append(documents, queryRow["id"]) } - resultsCloseErr := results.Close() - if resultsCloseErr != nil { - return documents, err - } - return documents, nil + err = results.Close() + return documents, err } func (db *DatabaseContext) CacheCompactActive() bool { From ba3cc93f7f1edd431156c4ae7e6b86f6952c02bb Mon Sep 17 00:00:00 2001 From: Tor Colvin Date: Tue, 2 Jan 2024 10:49:06 -0500 Subject: [PATCH 3/4] Update comment --- db/util_testing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/util_testing.go b/db/util_testing.go index a909d0077a..73ca812156 100644 --- a/db/util_testing.go +++ b/db/util_testing.go @@ -65,7 +65,7 @@ func isPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) (bool, error return len(docs) == 0, err } -// getPrimaryIndexDocuments returs true if there are no documents in the primary index +// getPrimaryIndexDocuments returs true if there are no documents in the primary index and returns the documents. If allDocuments is false, only check for a single document. func getPrimaryIndexDocuments(ctx context.Context, store base.N1QLStore, allDocuments bool) ([]string, error) { // Create the star channel query statement := fmt.Sprintf("SELECT META().id FROM %s", base.KeyspaceQueryToken) From 242dc6831f261c6432767f426c1cadcf174f97c7 Mon Sep 17 00:00:00 2001 From: Tor Colvin Date: Tue, 2 Jan 2024 11:37:26 -0500 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Ben Brooks --- db/util_testing.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db/util_testing.go b/db/util_testing.go index 73ca812156..245fce4aec 100644 --- a/db/util_testing.go +++ b/db/util_testing.go @@ -46,18 +46,18 @@ func WaitForPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) error { ) var retryError *base.RetryTimeoutError if errors.As(err, &retryError) { - files, err := getPrimaryIndexDocuments(ctx, store, true) + documents, err := getPrimaryIndexDocuments(ctx, store, true) if err != nil { - return fmt.Errorf("Error getting files from primary index: %w", err) + return fmt.Errorf("Error getting documents from primary index: %w", err) } - return fmt.Errorf("Documents left behind after waiting for primary index to be emptied: %s", files) + return fmt.Errorf("Documents left behind after waiting for primary index to be emptied: %s", documents) } return err } // isPrimaryIndexEmpty returns true if there are no documents in the primary index func isPrimaryIndexEmpty(ctx context.Context, store base.N1QLStore) (bool, error) { - // only look for a single file to make query faster + // only look for a single doc to make query faster docs, err := getPrimaryIndexDocuments(ctx, store, false) if err != nil { return false, err