summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Hirschhorn <max.hirschhorn@mongodb.com>2023-03-16 00:31:33 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-03-16 01:17:47 +0000
commit46bb04d7fdba4e4213534809973027d44029f05d (patch)
tree8a2ccfbe0695dbcf484be4f0534e0703ba11ef7d
parentca939e3cc87615cc33211efbc097283c5f53b68b (diff)
downloadmongo-46bb04d7fdba4e4213534809973027d44029f05d.tar.gz
SERVER-51835 Respect preference order in read preference tag set list.
Fixes the streamable and sdam replica set monitors to obey the documented preference order for matching against multiple tag sets. In particular, once a match is found, that tag set is used to find all eligible matching server members, and the remaining tag sets are ignored. (cherry picked from commit 7b5b262e93af9fd3773cc842816a3517ced81e09)
-rw-r--r--src/mongo/client/sdam/server_selector.cpp51
-rw-r--r--src/mongo/client/sdam/server_selector_test.cpp4
2 files changed, 31 insertions, 24 deletions
diff --git a/src/mongo/client/sdam/server_selector.cpp b/src/mongo/client/sdam/server_selector.cpp
index 5984e4ca9bb..a6bb84c18ee 100644
--- a/src/mongo/client/sdam/server_selector.cpp
+++ b/src/mongo/client/sdam/server_selector.cpp
@@ -233,35 +233,40 @@ bool SdamServerSelector::_containsAllTags(ServerDescriptionPtr server, const BSO
void SdamServerSelector::filterTags(std::vector<ServerDescriptionPtr>* servers,
const TagSet& tagSet) {
- const auto& checkTags = tagSet.getTagBSON();
+ const auto& tagSetList = tagSet.getTagBSON();
- if (checkTags.nFields() == 0)
+ if (tagSetList.isEmpty()) {
return;
+ }
- const auto predicate = [&](const ServerDescriptionPtr& s) {
- auto it = checkTags.begin();
- while (it != checkTags.end()) {
- if (it->isABSONObj()) {
- const BSONObj& tags = it->Obj();
- if (_containsAllTags(s, tags)) {
- // found a match -- don't remove the server
- return false;
- }
- } else {
- LOGV2_WARNING(
- 4671202,
- "Invalid tags specified for server selection; tags should be specified as "
- "bson Objects",
- "tag"_attr = *it);
- }
- ++it;
+ for (const auto& tagSetElem : tagSetList) {
+ if (tagSetElem.type() != BSONType::Object) {
+ LOGV2_WARNING(4671202,
+ "Invalid tag set specified for server selection; tag sets should be"
+ " specified as a BSON object",
+ "tag"_attr = tagSetElem);
+ continue;
}
- // remove the server
- return true;
- };
+ const auto predicate = [&](const ServerDescriptionPtr& s) {
+ const bool shouldRemove = !_containsAllTags(s, tagSetElem.embeddedObject());
+ return shouldRemove;
+ };
+
+ auto it = std::remove_if(servers->begin(), servers->end(), predicate);
+ // If none of the server descriptions match the tag set, then continue on to check the next
+ // tag set in the list. Otherwise, if at least one of the server descriptions match the tag
+ // set criteria, then we've found our preferred host(s) to read from.
+ if (it != servers->begin()) {
+ servers->erase(it, servers->end());
+ return;
+ }
+ }
- servers->erase(std::remove_if(servers->begin(), servers->end(), predicate), servers->end());
+ // Getting here means a non-empty tag set list was specified but none of the server descriptions
+ // matched any of the tag sets in the list. We've therefore failed to find any server
+ // description matching the read preference tag criteria.
+ servers->clear();
}
bool SdamServerSelector::recencyFilter(const ReadPreferenceSetting& readPref,
diff --git a/src/mongo/client/sdam/server_selector_test.cpp b/src/mongo/client/sdam/server_selector_test.cpp
index c12eaf2a4d9..400abf8013e 100644
--- a/src/mongo/client/sdam/server_selector_test.cpp
+++ b/src/mongo/client/sdam/server_selector_test.cpp
@@ -654,7 +654,9 @@ TEST_F(ServerSelectorTestFixture, ShouldFilterByTags) {
tags = TagSets::eastOrWestProductionSet;
servers = makeServerDescriptionList();
selector.filterTags(&servers, tags);
- ASSERT_EQ(2, servers.size());
+ ASSERT_EQ(1, servers.size());
+ ASSERT_EQ((std::map<std::string, std::string>{{"dc", "east"}, {"usage", "production"}}),
+ servers[0]->getTags());
tags = TagSets::testSet;
servers = makeServerDescriptionList();