diff options
author | Alex Li <alex.li@mongodb.com> | 2021-07-12 18:35:15 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-07-23 13:59:00 +0000 |
commit | 60a4229054cda93a50265a25d7a8a71ca2763e96 (patch) | |
tree | a21db5b649495d27bc89e77a80adfa0bcde0c167 /src | |
parent | 306a69a50245fb0787391c26597b02c04a156488 (diff) | |
download | mongo-60a4229054cda93a50265a25d7a8a71ca2763e96.tar.gz |
SERVER-55412 shardVersion propogated for mirrored reads
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands/command_mirroring_test.cpp | 187 | ||||
-rw-r--r-- | src/mongo/db/commands/count_cmd.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/distinct.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/find_and_modify.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands.cpp | 5 |
6 files changed, 163 insertions, 37 deletions
diff --git a/src/mongo/db/commands/command_mirroring_test.cpp b/src/mongo/db/commands/command_mirroring_test.cpp index 68b42d6ea30..286d20813a2 100644 --- a/src/mongo/db/commands/command_mirroring_test.cpp +++ b/src/mongo/db/commands/command_mirroring_test.cpp @@ -98,16 +98,28 @@ private: } const LogicalSessionId _lsid; + +protected: + const std::string kCollection = "test"; }; class UpdateCommandTest : public CommandMirroringTest { public: + void setUp() override { + CommandMirroringTest::setUp(); + shardVersion = boost::none; + } + std::string commandName() override { return "update"; } OpMsgRequest makeCommand(std::string coll, std::vector<BSONObj> updates) override { - auto request = CommandMirroringTest::makeCommand(coll, {}); + std::vector<BSONObj> args; + if (shardVersion) { + args.push_back(shardVersion.get()); + } + auto request = CommandMirroringTest::makeCommand(coll, args); // Directly add `updates` to `OpMsg::sequences` to emulate `OpMsg::parse()` behavior. OpMsg::DocumentSequence seq; @@ -120,13 +132,15 @@ public: return request; } + + boost::optional<BSONObj> shardVersion; }; TEST_F(UpdateCommandTest, NoQuery) { auto update = BSON("q" << BSONObj() << "u" << BSON("$set" << BSON("_id" << 1))); - auto mirroredObj = createCommandAndGetMirrored("my_collection", {update}); + auto mirroredObj = createCommandAndGetMirrored(kCollection, {update}); - ASSERT_EQ(mirroredObj["find"].String(), "my_collection"); + ASSERT_EQ(mirroredObj["find"].String(), kCollection); ASSERT_EQ(mirroredObj["filter"].Obj().toString(), "{}"); ASSERT(!mirroredObj.hasField("hint")); ASSERT(mirroredObj["singleBatch"].Bool()); @@ -136,9 +150,9 @@ TEST_F(UpdateCommandTest, NoQuery) { TEST_F(UpdateCommandTest, SingleQuery) { auto update = BSON("q" << BSON("qty" << BSON("$lt" << 50.0)) << "u" << BSON("$inc" << BSON("qty" << 1))); - auto mirroredObj = createCommandAndGetMirrored("products", {update}); + auto mirroredObj = createCommandAndGetMirrored(kCollection, {update}); - ASSERT_EQ(mirroredObj["find"].String(), "products"); + ASSERT_EQ(mirroredObj["find"].String(), kCollection); ASSERT_EQ(mirroredObj["filter"].Obj().toString(), "{ qty: { $lt: 50.0 } }"); ASSERT(!mirroredObj.hasField("hint")); ASSERT(mirroredObj["singleBatch"].Bool()); @@ -152,9 +166,9 @@ TEST_F(UpdateCommandTest, SingleQueryWithHintAndCollation) { << "fr") << "u" << BSON("$inc" << BSON("price" << 10))); - auto mirroredObj = createCommandAndGetMirrored("products", {update}); + auto mirroredObj = createCommandAndGetMirrored(kCollection, {update}); - ASSERT_EQ(mirroredObj["find"].String(), "products"); + ASSERT_EQ(mirroredObj["find"].String(), kCollection); ASSERT_EQ(mirroredObj["filter"].Obj().toString(), "{ price: { $gt: 100 } }"); ASSERT_EQ(mirroredObj["hint"].Obj().toString(), "{ price: 1 }"); ASSERT_EQ(mirroredObj["collation"].Obj().toString(), "{ locale: \"fr\" }"); @@ -169,15 +183,33 @@ TEST_F(UpdateCommandTest, MultipleQueries) { updates.emplace_back(BSON("q" << BSON("_id" << BSON("$eq" << i)) << "u" << BSON("$inc" << BSON("qty" << 1)))); } - auto mirroredObj = createCommandAndGetMirrored("products", updates); + auto mirroredObj = createCommandAndGetMirrored(kCollection, updates); - ASSERT_EQ(mirroredObj["find"].String(), "products"); + ASSERT_EQ(mirroredObj["find"].String(), kCollection); ASSERT_EQ(mirroredObj["filter"].Obj().toString(), "{ _id: { $eq: 0 } }"); ASSERT(!mirroredObj.hasField("hint")); ASSERT(mirroredObj["singleBatch"].Bool()); ASSERT_EQ(mirroredObj["batchSize"].Int(), 1); } +TEST_F(UpdateCommandTest, ValidateShardVersion) { + auto update = BSON("q" << BSONObj() << "u" << BSON("$set" << BSON("_id" << 1))); + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, {update}); + + ASSERT_FALSE(mirroredObj.hasField("shardVersion")); + } + + const auto kShardVersion = 123; + shardVersion = BSON("shardVersion" << kShardVersion); + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, {update}); + + ASSERT_TRUE(mirroredObj.hasField("shardVersion")); + ASSERT_EQ(mirroredObj["shardVersion"].Int(), kShardVersion); + } +} + class FindCommandTest : public CommandMirroringTest { public: std::string commandName() override { @@ -195,7 +227,8 @@ public: "min", "max", "batchSize", - "singleBatch"}; + "singleBatch", + "shardVersion"}; } void checkFieldNamesAreAllowed(BSONObj& mirroredObj) { @@ -229,9 +262,10 @@ TEST_F(FindCommandTest, MirrorableKeys) { BSON("noCursorTimeout" << true), BSON("awaitData" << true), BSON("allowPartialResults" << true), - BSON("collation" << BSONObj())}; + BSON("collation" << BSONObj()), + BSON("shardVersion" << BSONObj())}; - auto mirroredObj = createCommandAndGetMirrored("test", findArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, findArgs); checkFieldNamesAreAllowed(mirroredObj); } @@ -239,13 +273,12 @@ TEST_F(FindCommandTest, BatchSizeReconfiguration) { auto findArgs = { BSON("filter" << BSONObj()), BSON("batchSize" << 100), BSON("singleBatch" << false)}; - auto mirroredObj = createCommandAndGetMirrored("test", findArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, findArgs); ASSERT_EQ(mirroredObj["singleBatch"].Bool(), true); ASSERT_EQ(mirroredObj["batchSize"].Int(), 1); } TEST_F(FindCommandTest, ValidateMirroredQuery) { - constexpr auto collection = "restaurants"; const auto filter = BSON("rating" << BSON("$gte" << 9) << "cuisine" << "Italian"); constexpr auto skip = 10; @@ -258,6 +291,8 @@ TEST_F(FindCommandTest, ValidateMirroredQuery) { const auto min = BSONObj(); const auto max = BSONObj(); + const auto shardVersion = BSONObj(); + auto findArgs = {BSON("filter" << filter), BSON("skip" << skip), BSON("limit" << limit), @@ -265,11 +300,12 @@ TEST_F(FindCommandTest, ValidateMirroredQuery) { BSON("hint" << hint), BSON("collation" << collation), BSON("min" << min), - BSON("max" << max)}; + BSON("max" << max), + BSON("shardVersion" << shardVersion)}; - auto mirroredObj = createCommandAndGetMirrored(collection, findArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, findArgs); - ASSERT_EQ(mirroredObj["find"].String(), collection); + ASSERT_EQ(mirroredObj["find"].String(), kCollection); ASSERT(compareBSONObjs(mirroredObj["filter"].Obj(), filter)); ASSERT_EQ(mirroredObj["skip"].Int(), skip); ASSERT_EQ(mirroredObj["limit"].Int(), limit); @@ -278,6 +314,23 @@ TEST_F(FindCommandTest, ValidateMirroredQuery) { ASSERT(compareBSONObjs(mirroredObj["collation"].Obj(), collation)); ASSERT(compareBSONObjs(mirroredObj["min"].Obj(), min)); ASSERT(compareBSONObjs(mirroredObj["max"].Obj(), max)); + ASSERT(compareBSONObjs(mirroredObj["shardVersion"].Obj(), shardVersion)); +} + +TEST_F(FindCommandTest, ValidateShardVersion) { + std::vector<BSONObj> findArgs = {BSON("filter" << BSONObj())}; + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, findArgs); + ASSERT_FALSE(mirroredObj.hasField("shardVersion")); + } + + const auto kShardVersion = 123; + findArgs.push_back(BSON("shardVersion" << kShardVersion)); + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, findArgs); + ASSERT_TRUE(mirroredObj.hasField("shardVersion")); + ASSERT_EQ(mirroredObj["shardVersion"].Int(), kShardVersion); + } } class FindAndModifyCommandTest : public FindCommandTest { @@ -287,7 +340,7 @@ public: } std::vector<std::string> getAllowedKeys() const override { - return {"sort", "collation", "find", "filter", "batchSize", "singleBatch"}; + return {"sort", "collation", "find", "filter", "batchSize", "singleBatch", "shardVersion"}; } }; @@ -305,7 +358,7 @@ TEST_F(FindAndModifyCommandTest, MirrorableKeys) { BSON("collation" << BSONObj()), BSON("arrayFilters" << BSONArray())}; - auto mirroredObj = createCommandAndGetMirrored("test", findAndModifyArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, findAndModifyArgs); checkFieldNamesAreAllowed(mirroredObj); } @@ -315,13 +368,12 @@ TEST_F(FindAndModifyCommandTest, BatchSizeReconfiguration) { BSON("batchSize" << 100), BSON("singleBatch" << false)}; - auto mirroredObj = createCommandAndGetMirrored("test", findAndModifyArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, findAndModifyArgs); ASSERT_EQ(mirroredObj["singleBatch"].Bool(), true); ASSERT_EQ(mirroredObj["batchSize"].Int(), 1); } TEST_F(FindAndModifyCommandTest, ValidateMirroredQuery) { - constexpr auto collection = "people"; const auto query = BSON("name" << "Andy"); const auto sortObj = BSON("rating" << 1); @@ -336,15 +388,34 @@ TEST_F(FindAndModifyCommandTest, ValidateMirroredQuery) { BSON("upsert" << upsert), BSON("collation" << collation)}; - auto mirroredObj = createCommandAndGetMirrored(collection, findAndModifyArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, findAndModifyArgs); - ASSERT_EQ(mirroredObj["find"].String(), collection); + ASSERT_EQ(mirroredObj["find"].String(), kCollection); ASSERT(!mirroredObj.hasField("upsert")); ASSERT(compareBSONObjs(mirroredObj["filter"].Obj(), query)); ASSERT(compareBSONObjs(mirroredObj["sort"].Obj(), sortObj)); ASSERT(compareBSONObjs(mirroredObj["collation"].Obj(), collation)); } +TEST_F(FindAndModifyCommandTest, ValidateShardVersion) { + std::vector<BSONObj> findAndModifyArgs = {BSON("query" << BSON("name" + << "Andy")), + BSON("update" << BSON("$inc" << BSON("score" << 1)))}; + + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, findAndModifyArgs); + ASSERT_FALSE(mirroredObj.hasField("shardVersion")); + } + + const auto kShardVersion = 123; + findAndModifyArgs.push_back(BSON("shardVersion" << kShardVersion)); + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, findAndModifyArgs); + ASSERT_TRUE(mirroredObj.hasField("shardVersion")); + ASSERT_EQ(mirroredObj["shardVersion"].Int(), kShardVersion); + } +} + class DistinctCommandTest : public FindCommandTest { public: std::string commandName() override { @@ -352,7 +423,7 @@ public: } std::vector<std::string> getAllowedKeys() const override { - return {"distinct", "key", "query", "collation"}; + return {"distinct", "key", "query", "collation", "shardVersion"}; } }; @@ -361,33 +432,54 @@ TEST_F(DistinctCommandTest, MirrorableKeys) { << ""), BSON("query" << BSONObj()), BSON("readConcern" << BSONObj()), - BSON("collation" << BSONObj())}; + BSON("collation" << BSONObj()), + BSON("shardVersion" << BSONObj())}; - auto mirroredObj = createCommandAndGetMirrored("test", distinctArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, distinctArgs); checkFieldNamesAreAllowed(mirroredObj); } TEST_F(DistinctCommandTest, ValidateMirroredQuery) { - constexpr auto collection = "restaurants"; constexpr auto key = "rating"; const auto query = BSON("cuisine" << "italian"); const auto readConcern = BSON("level" << "majority"); const auto collation = BSON("strength" << 1); + const auto shardVersion = BSONObj(); auto distinctArgs = {BSON("key" << key), BSON("query" << query), BSON("readConcern" << readConcern), - BSON("collation" << collation)}; + BSON("collation" << collation), + BSON("shardVersion" << shardVersion)}; - auto mirroredObj = createCommandAndGetMirrored(collection, distinctArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, distinctArgs); - ASSERT_EQ(mirroredObj["distinct"].String(), collection); + ASSERT_EQ(mirroredObj["distinct"].String(), kCollection); ASSERT(!mirroredObj.hasField("readConcern")); ASSERT_EQ(mirroredObj["key"].String(), key); ASSERT(compareBSONObjs(mirroredObj["query"].Obj(), query)); ASSERT(compareBSONObjs(mirroredObj["collation"].Obj(), collation)); + ASSERT(compareBSONObjs(mirroredObj["shardVersion"].Obj(), shardVersion)); +} + +TEST_F(DistinctCommandTest, ValidateShardVersion) { + const auto kCollection = "test"; + + std::vector<BSONObj> distinctArgs = {BSON("distinct" << BSONObj())}; + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, distinctArgs); + ASSERT_FALSE(mirroredObj.hasField("shardVersion")); + } + + const auto kShardVersion = 123; + distinctArgs.push_back(BSON("shardVersion" << kShardVersion)); + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, distinctArgs); + ASSERT_TRUE(mirroredObj.hasField("shardVersion")); + ASSERT_EQ(mirroredObj["shardVersion"].Int(), kShardVersion); + } } class CountCommandTest : public FindCommandTest { @@ -397,7 +489,7 @@ public: } std::vector<std::string> getAllowedKeys() const override { - return {"count", "query", "skip", "limit", "hint", "collation"}; + return {"count", "query", "skip", "limit", "hint", "collation", "shardVersion"}; } }; @@ -407,28 +499,49 @@ TEST_F(CountCommandTest, MirrorableKeys) { BSON("skip" << 10), BSON("hint" << BSONObj()), BSON("readConcern" << BSONObj()), - BSON("collation" << BSONObj())}; + BSON("collation" << BSONObj()), + BSON("shardVersion" << BSONObj())}; - auto mirroredObj = createCommandAndGetMirrored("test", countArgs); + auto mirroredObj = createCommandAndGetMirrored(kCollection, countArgs); checkFieldNamesAreAllowed(mirroredObj); } TEST_F(CountCommandTest, ValidateMirroredQuery) { - constexpr auto collection = "orders"; const auto query = BSON("status" << "Delivered"); const auto hint = BSON("status" << 1); constexpr auto limit = 1000; + const auto shardVersion = BSONObj(); - auto countArgs = {BSON("query" << query), BSON("hint" << hint), BSON("limit" << limit)}; - auto mirroredObj = createCommandAndGetMirrored(collection, countArgs); + auto countArgs = {BSON("query" << query), + BSON("hint" << hint), + BSON("limit" << limit), + BSON("shardVersion" << shardVersion)}; + auto mirroredObj = createCommandAndGetMirrored(kCollection, countArgs); - ASSERT_EQ(mirroredObj["count"].String(), collection); + ASSERT_EQ(mirroredObj["count"].String(), kCollection); ASSERT(!mirroredObj.hasField("skip")); ASSERT(!mirroredObj.hasField("collation")); ASSERT(compareBSONObjs(mirroredObj["query"].Obj(), query)); ASSERT(compareBSONObjs(mirroredObj["hint"].Obj(), hint)); ASSERT_EQ(mirroredObj["limit"].Int(), limit); + ASSERT(compareBSONObjs(mirroredObj["shardVersion"].Obj(), shardVersion)); +} + +TEST_F(CountCommandTest, ValidateShardVersion) { + std::vector<BSONObj> countArgs = {BSON("count" << BSONObj())}; + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, countArgs); + ASSERT_FALSE(mirroredObj.hasField("shardVersion")); + } + + const auto kShardVersion = 123; + countArgs.push_back(BSON("shardVersion" << kShardVersion)); + { + auto mirroredObj = createCommandAndGetMirrored(kCollection, countArgs); + ASSERT_TRUE(mirroredObj.hasField("shardVersion")); + ASSERT_EQ(mirroredObj["shardVersion"].Int(), kShardVersion); + } } } // namespace diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp index 2d4769c5f86..59b336b961d 100644 --- a/src/mongo/db/commands/count_cmd.cpp +++ b/src/mongo/db/commands/count_cmd.cpp @@ -309,6 +309,7 @@ public: keyBob.append("limit", 1); keyBob.append("hint", 1); keyBob.append("collation", 1); + keyBob.append("shardVersion", 1); return keyBob.obj(); }(); diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp index 6c9dba828d3..96054086f0f 100644 --- a/src/mongo/db/commands/distinct.cpp +++ b/src/mongo/db/commands/distinct.cpp @@ -339,6 +339,7 @@ public: keyBob.append("key", 1); keyBob.append("query", 1); keyBob.append("collation", 1); + keyBob.append("shardVersion", 1); return keyBob.obj(); }(); diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp index 52fd39f3683..b7066244fcc 100644 --- a/src/mongo/db/commands/find_and_modify.cpp +++ b/src/mongo/db/commands/find_and_modify.cpp @@ -732,6 +732,11 @@ void CmdFindAndModify::Invocation::appendMirrorableRequest(BSONObjBuilder* bob) *req.getCollation()); } + const auto& rawCmd = unparsedRequest().body; + if (const auto& shardVersion = rawCmd.getField("shardVersion"); !shardVersion.eoo()) { + bob->append(shardVersion); + } + // Prevent the find from returning multiple documents since we can bob->append("batchSize", 1); bob->append("singleBatch", true); diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp index c417a7473f1..e3a2e22a910 100644 --- a/src/mongo/db/commands/find_cmd.cpp +++ b/src/mongo/db/commands/find_cmd.cpp @@ -586,6 +586,7 @@ public: keyBob.append("collation", 1); keyBob.append("min", 1); keyBob.append("max", 1); + keyBob.append("shardVersion", 1); return keyBob.obj(); }(); diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp index 1397fe6ce09..d86302032dd 100644 --- a/src/mongo/db/commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands.cpp @@ -1172,6 +1172,11 @@ public: invariant(!_commandObj.isEmpty()); + if (const auto& shardVersion = _commandObj.getField("shardVersion"); + !shardVersion.eoo()) { + bob->append(shardVersion); + } + bob->append("find", _commandObj["update"].String()); extractQueryDetails(_updateOpObj, bob); bob->append("batchSize", 1); |