diff options
author | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2023-03-16 00:31:33 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-03-16 01:17:47 +0000 |
commit | 46bb04d7fdba4e4213534809973027d44029f05d (patch) | |
tree | 8a2ccfbe0695dbcf484be4f0534e0703ba11ef7d | |
parent | ca939e3cc87615cc33211efbc097283c5f53b68b (diff) | |
download | mongo-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.cpp | 51 | ||||
-rw-r--r-- | src/mongo/client/sdam/server_selector_test.cpp | 4 |
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(); |