Skip to content

Commit a85f5a6

Browse files
authored
REP-5319 Only create partition-verification tasks in generation 0. (#49)
When the verifier finds a metadata mismatch it enqueues a recheck of that metadata in the next generation. This is fine, but since metadata-check tasks also partition documents & create document-checking tasks for those partitions, what’s been happening is that any time some collection metadata property (e.g., an index) mismatches, tasks are enqueued to recheck all of the collection’s documents. Since the partitioning stuff is only appropriate for generation 0, this changeset restricts that behavior accordingly. For convenience this also adds mslices.Of from mongosync’s mongo-go.
1 parent 8497935 commit a85f5a6

File tree

4 files changed

+118
-14
lines changed

4 files changed

+118
-14
lines changed

internal/verifier/migration_verifier.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,22 +1082,25 @@ func (verifier *Verifier) verifyMetadataAndPartitionCollection(ctx context.Conte
10821082
task.Status = verificationTaskMetadataMismatch
10831083
}
10841084

1085-
partitions, shardKeys, docsCount, bytesCount, err := verifier.partitionAndInspectNamespace(ctx, srcNs)
1086-
if err != nil {
1087-
task.Status = verificationTaskFailed
1088-
verifier.logger.Error().Msgf("[Worker %d] Error partitioning collection: %+v", workerNum, err)
1089-
return
1090-
}
1091-
verifier.logger.Debug().Msgf("[Worker %d] split collection “%s” into %d partitions", workerNum, srcNs, len(partitions))
1092-
1093-
task.SourceDocumentCount = docsCount
1094-
task.SourceByteCount = bytesCount
1095-
1096-
for _, partition := range partitions {
1097-
_, err := verifier.InsertPartitionVerificationTask(partition, shardKeys, dstNs)
1085+
if task.Generation == 0 {
1086+
partitions, shardKeys, docsCount, bytesCount, err := verifier.partitionAndInspectNamespace(ctx, srcNs)
10981087
if err != nil {
10991088
task.Status = verificationTaskFailed
1100-
verifier.logger.Error().Msgf("[Worker %d] Error inserting verifier tasks: %+v", workerNum, err)
1089+
1090+
verifier.logger.Error().Msgf("[Worker %d] Error partitioning collection: %+v", workerNum, err)
1091+
return
1092+
}
1093+
verifier.logger.Debug().Msgf("[Worker %d] split collection “%s” into %d partitions", workerNum, srcNs, len(partitions))
1094+
1095+
task.SourceDocumentCount = docsCount
1096+
task.SourceByteCount = bytesCount
1097+
1098+
for _, partition := range partitions {
1099+
_, err := verifier.InsertPartitionVerificationTask(partition, shardKeys, dstNs)
1100+
if err != nil {
1101+
task.Status = verificationTaskFailed
1102+
verifier.logger.Error().Msgf("[Worker %d] Error inserting verifier tasks: %+v", workerNum, err)
1103+
}
11011104
}
11021105
}
11031106

internal/verifier/migration_verifier_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
"github.com/10gen/migration-verifier/internal/partitions"
2020
"github.com/10gen/migration-verifier/internal/testutil"
21+
"github.com/10gen/migration-verifier/mslices"
2122
"github.com/cespare/permute/v2"
2223
"github.com/rs/zerolog"
2324
"github.com/samber/lo"
@@ -1283,6 +1284,68 @@ func (suite *IntegrationTestSuite) TestVerificationStatus() {
12831284
suite.Equal(1, status.CompletedTasks, "completed tasks not equal")
12841285
}
12851286

1287+
func (suite *IntegrationTestSuite) TestMetadataMismatchAndPartitioning() {
1288+
ctx := suite.Context()
1289+
1290+
srcColl := suite.srcMongoClient.Database(suite.DBNameForTest()).Collection("coll")
1291+
dstColl := suite.dstMongoClient.Database(suite.DBNameForTest()).Collection("coll")
1292+
1293+
verifier := suite.BuildVerifier()
1294+
1295+
ns := srcColl.Database().Name() + "." + srcColl.Name()
1296+
verifier.SetSrcNamespaces([]string{ns})
1297+
verifier.SetDstNamespaces([]string{ns})
1298+
verifier.SetNamespaceMap()
1299+
1300+
for _, coll := range mslices.Of(srcColl, dstColl) {
1301+
_, err := coll.InsertOne(ctx, bson.M{"_id": 1, "x": 42})
1302+
suite.Require().NoError(err)
1303+
}
1304+
1305+
_, err := srcColl.Indexes().CreateOne(
1306+
ctx,
1307+
mongo.IndexModel{
1308+
Keys: bson.D{{"foo", 1}},
1309+
},
1310+
)
1311+
suite.Require().NoError(err)
1312+
1313+
runner := RunVerifierCheck(ctx, suite.T(), verifier)
1314+
runner.AwaitGenerationEnd()
1315+
1316+
cursor, err := verifier.verificationTaskCollection().Find(
1317+
ctx,
1318+
bson.M{"generation": 0},
1319+
options.Find().SetSort(bson.M{"type": 1}),
1320+
)
1321+
suite.Require().NoError(err)
1322+
1323+
var tasks []VerificationTask
1324+
suite.Require().NoError(cursor.All(ctx, &tasks))
1325+
1326+
suite.Require().Len(tasks, 2)
1327+
suite.Require().Equal(verificationTaskVerifyDocuments, tasks[0].Type)
1328+
suite.Require().Equal(verificationTaskCompleted, tasks[0].Status)
1329+
suite.Require().Equal(verificationTaskVerifyCollection, tasks[1].Type)
1330+
suite.Require().Equal(verificationTaskMetadataMismatch, tasks[1].Status)
1331+
1332+
runner.StartNextGeneration()
1333+
runner.AwaitGenerationEnd()
1334+
1335+
cursor, err = verifier.verificationTaskCollection().Find(
1336+
ctx,
1337+
bson.M{"generation": 1},
1338+
options.Find().SetSort(bson.M{"type": 1}),
1339+
)
1340+
suite.Require().NoError(err)
1341+
1342+
suite.Require().NoError(cursor.All(ctx, &tasks))
1343+
1344+
suite.Require().Len(tasks, 1, "generation 1 should only have done 1 task")
1345+
suite.Require().Equal(verificationTaskVerifyCollection, tasks[0].Type)
1346+
suite.Require().Equal(verificationTaskMetadataMismatch, tasks[0].Status)
1347+
}
1348+
12861349
func (suite *IntegrationTestSuite) TestGenerationalRechecking() {
12871350
zerolog.SetGlobalLevel(zerolog.DebugLevel)
12881351
verifier := suite.BuildVerifier()

mslices/slices.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package mslices
2+
3+
// This package complements the Go standard library’s package of the
4+
// same name with broadly-useful tools that the standard library lacks.
5+
6+
// Of returns a slice out of the given arguments. It’s syntactic sugar
7+
// to capitalize on Go’s type inference, similar to
8+
// [this declined feature proposal](https://github.com/golang/go/issues/47709).
9+
func Of[T any](pieces ...T) []T {
10+
return append([]T{}, pieces...)
11+
}

mslices/slices_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package mslices
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/suite"
7+
)
8+
9+
type mySuite struct {
10+
suite.Suite
11+
}
12+
13+
func TestUnitTestSuite(t *testing.T) {
14+
suite.Run(t, &mySuite{})
15+
}
16+
17+
func (s *mySuite) Test_Of() {
18+
slc := Of(12, 23, 34)
19+
20+
s.Assert().IsType([]int{}, slc, "expected type")
21+
22+
a := []int{1, 2, 3}
23+
b := Of(a...)
24+
a[0] = 4
25+
26+
s.Assert().Equal(1, b[0], "should copy slice")
27+
}

0 commit comments

Comments
 (0)