summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Li <alex.li@mongodb.com>2021-07-12 18:35:15 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-20 18:36:59 +0000
commita456bd18efff4c1af30902ab4b1bad8627fc3c42 (patch)
treeca4a91665b33efbbc080813dd7317926fe8bf1b8
parent3641c00be722f394a2b0987cfcac023930e5bbf1 (diff)
downloadmongo-a456bd18efff4c1af30902ab4b1bad8627fc3c42.tar.gz
SERVER-55412 shardVersion propogated for mirrored reads
(cherry picked from commit 03364be4054d3d411c55a5b712e3d0733865eecd)
-rw-r--r--src/mongo/db/commands/command_mirroring_test.cpp187
-rw-r--r--src/mongo/db/commands/count_cmd.cpp1
-rw-r--r--src/mongo/db/commands/distinct.cpp1
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp1
-rw-r--r--src/mongo/db/commands/find_cmd.cpp1
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp5
6 files changed, 159 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 0e04440fe75..17da9ac3d92 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -281,6 +281,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 145e901b27e..8ecdb6e22ee 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -322,6 +322,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 8c2965e0b49..22328112d79 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -538,6 +538,7 @@ public:
BSONObjBuilder keyBob;
keyBob.append("sort", 1);
keyBob.append("collation", 1);
+ keyBob.append("shardVersion", 1);
return keyBob.obj();
}();
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 6a410c0c1d3..9f495c9760e 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -606,6 +606,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/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index 8241c5e3de6..14a6d491c71 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -373,6 +373,11 @@ private:
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);