From 8f63fa71c929990752a8399212e63ffb3517c310 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 30 May 2018 15:27:41 +0300 Subject: [PATCH] Cache updater username resolve results. --- Telegram/SourceFiles/core/update_checker.cpp | 137 ++++++++++--------- 1 file changed, 76 insertions(+), 61 deletions(-) diff --git a/Telegram/SourceFiles/core/update_checker.cpp b/Telegram/SourceFiles/core/update_checker.cpp index e851ea218..49678643b 100644 --- a/Telegram/SourceFiles/core/update_checker.cpp +++ b/Telegram/SourceFiles/core/update_checker.cpp @@ -247,7 +247,9 @@ private: using Checker::fail; base::lambda failHandler(); - void gotFeed(const MTPcontacts_ResolvedPeer &result); + void resolveChannel( + const QString &username, + base::lambda callback); void gotMessage(const MTPmessages_Messages &result); base::optional parseMessage( const MTPmessages_Messages &result) const; @@ -255,9 +257,6 @@ private: FileLocation validateLatestLocation( uint64 availableVersion, const FileLocation &location) const; - void resolvedFiles( - const MTPcontacts_ResolvedPeer &result, - const FileLocation &location); void gotFile(const MTPmessages_Messages &result); base::optional parseFile( const MTPmessages_Messages &result) const; @@ -1255,22 +1254,12 @@ void MtpChecker::start() { return; } constexpr auto kFeedUsername = "tdhbcfeed"; - - _mtp.send( - MTPcontacts_ResolveUsername(MTP_string(kFeedUsername)), - [=](const MTPcontacts_ResolvedPeer &result) { gotFeed(result); }, - failHandler()); -} - -void MtpChecker::gotFeed(const MTPcontacts_ResolvedPeer &result) { - Expects(result.type() == mtpc_contacts_resolvedPeer); - - if (const auto channel = ExtractChannel(result)) { + resolveChannel(kFeedUsername, [=](const MTPInputChannel &channel) { _mtp.send( MTPmessages_GetHistory( MTP_inputPeerChannel( - channel->c_inputChannel().vchannel_id, - channel->c_inputChannel().vaccess_hash), + channel.c_inputChannel().vchannel_id, + channel.c_inputChannel().vaccess_hash), MTP_int(0), // offset_id MTP_int(0), // offset_date MTP_int(0), // add_offset @@ -1280,28 +1269,74 @@ void MtpChecker::gotFeed(const MTPcontacts_ResolvedPeer &result) { MTP_int(0)), // hash [=](const MTPmessages_Messages &result) { gotMessage(result); }, failHandler()); - } else { - LOG(("Update Error: MTP feed channel not found.")); + }); +} + +void MtpChecker::resolveChannel( + const QString &username, + base::lambda callback) { + const auto failed = [&] { + LOG(("Update Error: MTP channel '%1' resolve failed." + ).arg(username)); fail(); + }; + if (!AuthSession::Exists()) { + failed(); + return; } + + struct ResolveResult { + base::weak_ptr auth; + MTPInputChannel channel; + }; + static std::map ResolveCache; + + const auto i = ResolveCache.find(username); + if (i != end(ResolveCache)) { + if (i->second.auth.get() == &Auth()) { + callback(i->second.channel); + return; + } + ResolveCache.erase(i); + } + + const auto doneHandler = [=](const MTPcontacts_ResolvedPeer &result) { + Expects(result.type() == mtpc_contacts_resolvedPeer); + + if (const auto channel = ExtractChannel(result)) { + ResolveCache.emplace( + username, + ResolveResult { base::make_weak(&Auth()), *channel }); + callback(*channel); + } else { + failed(); + } + }; + _mtp.send( + MTPcontacts_ResolveUsername(MTP_string(username)), + doneHandler, + failHandler()); } void MtpChecker::gotMessage(const MTPmessages_Messages &result) { - if (const auto location = parseMessage(result)) { - if (location->username.isEmpty()) { - done(nullptr); - } else { - const auto got = [=](const MTPcontacts_ResolvedPeer &result) { - resolvedFiles(result, *location); - }; - _mtp.send( - MTPcontacts_ResolveUsername(MTP_string(location->username)), - got, - failHandler()); - } - } else { + const auto location = parseMessage(result); + if (!location) { fail(); + return; + } else if (location->username.isEmpty()) { + done(nullptr); + return; } + resolveChannel(location->username, [=](const MTPInputChannel &channel) { + _mtp.send( + MTPchannels_GetMessages( + channel, + MTP_vector( + 1, + MTP_inputMessageID(MTP_int(location->postId)))), + [=](const MTPmessages_Messages &result) { gotFile(result); }, + failHandler()); + }); } auto MtpChecker::parseMessage(const MTPmessages_Messages &result) const @@ -1371,27 +1406,6 @@ auto MtpChecker::validateLatestLocation( return (availableVersion <= myVersion) ? FileLocation() : location; } -void MtpChecker::resolvedFiles( - const MTPcontacts_ResolvedPeer &result, - const FileLocation &location) { - Expects(result.type() == mtpc_contacts_resolvedPeer); - - if (const auto channel = ExtractChannel(result)) { - _mtp.send( - MTPchannels_GetMessages( - *channel, - MTP_vector( - 1, - MTP_inputMessageID(MTP_int(location.postId)))), - [=](const MTPmessages_Messages &result) { gotFile(result); }, - failHandler()); - } else { - LOG(("Update Error: MTP files channel not found: '%1'." - ).arg(location.username)); - fail(); - } -} - void MtpChecker::gotFile(const MTPmessages_Messages &result) { if (const auto file = parseFile(result)) { done(std::make_shared( @@ -1576,7 +1590,7 @@ private: void startImplementation( not_null which, std::unique_ptr checker); - void tryLoaders(); + bool tryLoaders(); void handleTimeout(); void checkerDone( not_null which, @@ -1830,20 +1844,19 @@ void Updater::handleTimeout() { }; reset(_httpImplementation); reset(_mtpImplementation); - tryLoaders(); + if (!tryLoaders()) { + cSetLastUpdateCheck(0); + _timer.callOnce(kUpdaterTimeout); + } } else if (_action == Action::Loading) { _failed.fire({}); } - if (_action == Action::Waiting) { - cSetLastUpdateCheck(0); - _timer.callOnce(kUpdaterTimeout); - } } -void Updater::tryLoaders() { +bool Updater::tryLoaders() { if (_httpImplementation.checker || _mtpImplementation.checker) { // Some checkers didn't finish yet. - return; + return true; } _retryTimer.cancel(); @@ -1871,6 +1884,7 @@ void Updater::tryLoaders() { }; if (_mtpImplementation.failed && _httpImplementation.failed) { _failed.fire({}); + return false; } else if (!_mtpImplementation.loader) { tryOne(_httpImplementation); } else if (!_httpImplementation.loader) { @@ -1881,6 +1895,7 @@ void Updater::tryLoaders() { : _httpImplementation); _usingMtprotoLoader = !_usingMtprotoLoader; } + return true; } void Updater::finalize(QString filepath) {