From d809329044ff88db80621f0a2adb971537fdba35 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 3 Mar 2024 00:39:11 +0300 Subject: [PATCH] Combine resolveUsername queries. --- td/telegram/ContactsManager.cpp | 2 +- td/telegram/DialogManager.cpp | 84 ++++++++++++++++++++------------- td/telegram/DialogManager.h | 10 ++-- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 0e8f9bff4..f6e230081 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -13436,7 +13436,7 @@ void ContactsManager::on_get_channel_participants( } if (participant_count != -1 || administrator_count != -1) { - auto channel_full = get_channel_full_force(channel_id, true, "on_get_channel_participants_success"); + auto channel_full = get_channel_full_force(channel_id, true, "on_get_channel_participants"); if (channel_full != nullptr) { if (administrator_count == -1) { administrator_count = channel_full->administrator_count; diff --git a/td/telegram/DialogManager.cpp b/td/telegram/DialogManager.cpp index 18bc6f992..db0239579 100644 --- a/td/telegram/DialogManager.cpp +++ b/td/telegram/DialogManager.cpp @@ -103,15 +103,13 @@ class CheckChannelUsernameQuery final : public Td::ResultHandler { }; class ResolveUsernameQuery final : public Td::ResultHandler { - Promise promise_; - string username_; + Promise promise_; public: - explicit ResolveUsernameQuery(Promise &&promise) : promise_(std::move(promise)) { + explicit ResolveUsernameQuery(Promise &&promise) : promise_(std::move(promise)) { } void send(const string &username) { - username_ = username; send_query(G()->net_query_creator().create(telegram_api::contacts_resolveUsername(username))); } @@ -126,15 +124,10 @@ class ResolveUsernameQuery final : public Td::ResultHandler { td_->contacts_manager_->on_get_users(std::move(ptr->users_), "ResolveUsernameQuery"); td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "ResolveUsernameQuery"); - td_->dialog_manager_->on_resolved_username(username_, DialogId(ptr->peer_)); - - promise_.set_value(Unit()); + promise_.set_value(DialogId(ptr->peer_)); } void on_error(Status status) final { - if (status.message() == Slice("USERNAME_NOT_OCCUPIED")) { - td_->dialog_manager_->drop_username(username_); - } promise_.set_error(std::move(status)); } }; @@ -1912,7 +1905,54 @@ td_api::object_ptr DialogManager::get_check_cha } void DialogManager::send_resolve_dialog_username_query(const string &username, Promise &&promise) { - td_->create_handler(std::move(promise))->send(username); + CHECK(!username.empty()); + auto &queries = resolve_dialog_username_queries_[username]; + queries.push_back(std::move(promise)); + if (queries.size() != 1u) { + return; + } + auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), username](Result r_dialog_id) { + send_closure(actor_id, &DialogManager::on_resolved_username, username, std::move(r_dialog_id)); + }); + td_->create_handler(std::move(query_promise))->send(username); +} + +void DialogManager::on_resolved_username(const string &username, Result r_dialog_id) { + G()->ignore_result_if_closing(r_dialog_id); + auto it = resolve_dialog_username_queries_.find(username); + CHECK(it != resolve_dialog_username_queries_.end()); + auto promises = std::move(it->second); + CHECK(!promises.empty()); + resolve_dialog_username_queries_.erase(it); + if (r_dialog_id.is_error()) { + auto error_message = r_dialog_id.error().message(); + if (error_message == Slice("USERNAME_NOT_OCCUPIED")) { + drop_username(username); + } + return fail_promises(promises, r_dialog_id.move_as_error()); + } + + auto dialog_id = r_dialog_id.ok(); + if (!dialog_id.is_valid()) { + LOG(ERROR) << "Resolve username \"" << username << "\" to invalid " << dialog_id; + return fail_promises(promises, Status::Error(500, "Chat not found")); + } + + auto cleaned_username = clean_username(username); + if (cleaned_username.empty()) { + return fail_promises(promises, Status::Error(500, "Invalid username")); + } + + auto resolved_username = resolved_usernames_.get(cleaned_username); + if (resolved_username.dialog_id.is_valid()) { + LOG_IF(ERROR, resolved_username.dialog_id != dialog_id) + << "Resolve username \"" << username << "\" to " << dialog_id << ", but have it in " + << resolved_username.dialog_id; + return set_promises(promises); + } + + inaccessible_resolved_usernames_[cleaned_username] = dialog_id; + set_promises(promises); } void DialogManager::resolve_dialog(const string &username, ChannelId channel_id, Promise promise) { @@ -2038,28 +2078,6 @@ void DialogManager::reload_voice_chat_on_search(const string &username) { } } -void DialogManager::on_resolved_username(const string &username, DialogId dialog_id) { - if (!dialog_id.is_valid()) { - LOG(ERROR) << "Resolve username \"" << username << "\" to invalid " << dialog_id; - return; - } - - auto cleaned_username = clean_username(username); - if (cleaned_username.empty()) { - return; - } - - auto resolved_username = resolved_usernames_.get(cleaned_username); - if (resolved_username.dialog_id.is_valid()) { - LOG_IF(ERROR, resolved_username.dialog_id != dialog_id) - << "Resolve username \"" << username << "\" to " << dialog_id << ", but have it in " - << resolved_username.dialog_id; - return; - } - - inaccessible_resolved_usernames_[cleaned_username] = dialog_id; -} - void DialogManager::drop_username(const string &username) { auto cleaned_username = clean_username(username); if (cleaned_username.empty()) { diff --git a/td/telegram/DialogManager.h b/td/telegram/DialogManager.h index 31159c973..ea01b0e60 100644 --- a/td/telegram/DialogManager.h +++ b/td/telegram/DialogManager.h @@ -204,10 +204,6 @@ class DialogManager final : public Actor { void reload_voice_chat_on_search(const string &username); - void on_resolved_username(const string &username, DialogId dialog_id); - - void drop_username(const string &username); - private: static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title @@ -225,6 +221,10 @@ class DialogManager final : public Actor { void send_resolve_dialog_username_query(const string &username, Promise &&promise); + void on_resolved_username(const string &username, Result r_dialog_id); + + void drop_username(const string &username); + void on_resolve_dialog(const string &username, ChannelId channel_id, Promise &&promise); class UploadDialogPhotoCallback; @@ -260,6 +260,8 @@ class DialogManager final : public Actor { WaitFreeHashMap inaccessible_resolved_usernames_; FlatHashSet reload_voice_chat_on_search_usernames_; + FlatHashMap>> resolve_dialog_username_queries_; + Td *td_; ActorShared<> parent_; };