From 55ad2e5f86bc466f8a7678665dd638be2bb60a4f Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 14 Sep 2021 11:31:21 +0300 Subject: [PATCH] Load recent dialogs in one pass. --- td/telegram/RecentDialogList.cpp | 139 +++++++++++++++---------------- td/telegram/RecentDialogList.h | 8 +- 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/td/telegram/RecentDialogList.cpp b/td/telegram/RecentDialogList.cpp index 5a552038d..05ceccd23 100644 --- a/td/telegram/RecentDialogList.cpp +++ b/td/telegram/RecentDialogList.cpp @@ -29,7 +29,7 @@ string RecentDialogList::get_binlog_key() const { } void RecentDialogList::save_dialogs() const { - if (dialogs_loaded_ < 2) { + if (!is_loaded_) { return; } CHECK(removed_dialog_ids_.empty()); @@ -55,7 +55,7 @@ void RecentDialogList::save_dialogs() const { default: UNREACHABLE(); } - if (!username.empty()) { + if (!username.empty() && username.find(',') == string::npos) { sb << '@' << username; continue; } @@ -70,84 +70,83 @@ void RecentDialogList::save_dialogs() const { } void RecentDialogList::load_dialogs(Promise &&promise) { - if (dialogs_loaded_ >= 2) { + if (is_loaded_) { return promise.set_value(Unit()); } - string found_dialogs_str = G()->td_db()->get_binlog_pmc()->get(get_binlog_key()); - if (found_dialogs_str.empty()) { - dialogs_loaded_ = 2; - removed_dialog_ids_.clear(); - if (!dialog_ids_.empty()) { - save_dialogs(); - } - return promise.set_value(Unit()); + load_list_queries_.push_back(std::move(promise)); + if (load_list_queries_.size() != 1) { + return; } - auto found_dialogs = full_split(found_dialogs_str, ','); - if (dialogs_loaded_ == 1 && resolve_dialogs_multipromise_.promise_count() == 0) { - // queries was sent and have already been finished - auto newly_found_dialogs = std::move(dialog_ids_); - dialog_ids_.clear(); + auto found_dialogs = full_split(G()->td_db()->get_binlog_pmc()->get(get_binlog_key()), ','); + MultiPromiseActorSafe mpas{"LoadRecentDialogListMultiPromiseActor"}; + mpas.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), found_dialogs](Unit) mutable { + send_closure(actor_id, &RecentDialogList::on_load_dialogs, std::move(found_dialogs)); + })); + mpas.set_ignore_errors(true); + auto lock = mpas.get_promise(); - for (auto it = found_dialogs.rbegin(); it != found_dialogs.rend(); ++it) { - DialogId dialog_id; - if ((*it)[0] == '@') { - dialog_id = td_->messages_manager_->resolve_dialog_username(it->substr(1)); - } else { - dialog_id = DialogId(to_integer(*it)); - } - if (dialog_id.is_valid() && removed_dialog_ids_.count(dialog_id) == 0 && - td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) { - td_->messages_manager_->force_create_dialog(dialog_id, "recent dialog"); - do_add_dialog(dialog_id); - } + vector dialog_ids; + for (auto &found_dialog : found_dialogs) { + if (found_dialog[0] == '@') { + td_->messages_manager_->search_public_dialog(found_dialog, false, mpas.get_promise()); + } else { + dialog_ids.push_back(DialogId(to_integer(found_dialog))); } - for (auto it = newly_found_dialogs.rbegin(); it != newly_found_dialogs.rend(); ++it) { - do_add_dialog(*it); + } + if (!dialog_ids.empty()) { + if (G()->parameters().use_message_db) { + td_->messages_manager_->load_dialogs(std::move(dialog_ids), mpas.get_promise()); + } else { + td_->messages_manager_->get_dialogs_from_list( + DialogListId(FolderId::main()), 102, + PromiseCreator::lambda([promise = mpas.get_promise()](td_api::object_ptr &&chats) mutable { + promise.set_value(Unit()); + })); + td_->contacts_manager_->search_contacts("", 1, mpas.get_promise()); } - dialogs_loaded_ = 2; - removed_dialog_ids_.clear(); - if (!newly_found_dialogs.empty()) { - save_dialogs(); - } - return promise.set_value(Unit()); } - resolve_dialogs_multipromise_.add_promise(std::move(promise)); - if (dialogs_loaded_ == 0) { - dialogs_loaded_ = 1; + lock.set_value(Unit()); +} - resolve_dialogs_multipromise_.set_ignore_errors(true); - auto lock = resolve_dialogs_multipromise_.get_promise(); +void RecentDialogList::on_load_dialogs(vector &&found_dialogs) { + auto promises = std::move(load_list_queries_); + CHECK(!promises.empty()); - vector dialog_ids; - for (auto &found_dialog : found_dialogs) { - if (found_dialog[0] == '@') { - td_->messages_manager_->search_public_dialog(found_dialog, false, resolve_dialogs_multipromise_.get_promise()); - } else { - dialog_ids.push_back(DialogId(to_integer(found_dialog))); - } + auto newly_found_dialogs = std::move(dialog_ids_); + reset_to_empty(dialog_ids_); + + for (auto it = found_dialogs.rbegin(); it != found_dialogs.rend(); ++it) { + DialogId dialog_id; + if ((*it)[0] == '@') { + dialog_id = td_->messages_manager_->resolve_dialog_username(it->substr(1)); + } else { + dialog_id = DialogId(to_integer(*it)); } - if (!dialog_ids.empty()) { - if (G()->parameters().use_message_db) { - td_->messages_manager_->load_dialogs(std::move(dialog_ids), resolve_dialogs_multipromise_.get_promise()); - } else { - td_->messages_manager_->get_dialogs_from_list( - DialogListId(FolderId::main()), 102, - PromiseCreator::lambda( - [promise = resolve_dialogs_multipromise_.get_promise()]( - td_api::object_ptr &&chats) mutable { promise.set_value(Unit()); })); - td_->contacts_manager_->search_contacts("", 1, resolve_dialogs_multipromise_.get_promise()); - } + if (dialog_id.is_valid() && removed_dialog_ids_.count(dialog_id) == 0 && + td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) { + td_->messages_manager_->force_create_dialog(dialog_id, "recent dialog"); + do_add_dialog(dialog_id); } + } + for (auto it = newly_found_dialogs.rbegin(); it != newly_found_dialogs.rend(); ++it) { + do_add_dialog(*it); + } + is_loaded_ = true; + removed_dialog_ids_.clear(); + if (!newly_found_dialogs.empty()) { + save_dialogs(); + } - lock.set_value(Unit()); + for (auto &promise : promises) { + promise.set_value(Unit()); } } void RecentDialogList::add_dialog(DialogId dialog_id) { - if (dialogs_loaded_ != 2) { + if (!is_loaded_) { load_dialogs(Promise()); } if (do_add_dialog(dialog_id)) { @@ -177,18 +176,18 @@ bool RecentDialogList::do_add_dialog(DialogId dialog_id) { } void RecentDialogList::remove_dialog(DialogId dialog_id) { - if (dialogs_loaded_ != 2) { + if (!is_loaded_) { load_dialogs(Promise()); } if (td::remove(dialog_ids_, dialog_id)) { save_dialogs(); - } else if (dialogs_loaded_ != 2) { + } else if (!is_loaded_) { removed_dialog_ids_.insert(dialog_id); } } void RecentDialogList::update_dialogs() { - CHECK(dialogs_loaded_ == 2); + CHECK(is_loaded_); vector dialog_ids; for (auto dialog_id : dialog_ids_) { if (!td_->messages_manager_->have_dialog(dialog_id)) { @@ -231,23 +230,23 @@ void RecentDialogList::update_dialogs() { std::pair> RecentDialogList::get_dialogs(int32 limit, Promise &&promise) { load_dialogs(std::move(promise)); - if (dialogs_loaded_ != 2) { + if (!is_loaded_) { return {}; } update_dialogs(); - size_t result_size = min(static_cast(limit), dialog_ids_.size()); - return {narrow_cast(dialog_ids_.size()), - vector(dialog_ids_.begin(), dialog_ids_.begin() + result_size)}; + CHECK(limit >= 0); + int32 total_count = narrow_cast(dialog_ids_.size()); + return {total_count, vector(dialog_ids_.begin(), dialog_ids_.begin() + min(limit, total_count))}; } void RecentDialogList::clear_dialogs() { - if (dialog_ids_.empty() && dialogs_loaded_ == 2) { + if (dialog_ids_.empty() && is_loaded_) { return; } - dialogs_loaded_ = 2; + is_loaded_ = true; dialog_ids_.clear(); removed_dialog_ids_.clear(); save_dialogs(); diff --git a/td/telegram/RecentDialogList.h b/td/telegram/RecentDialogList.h index 27698dbec..73d5e4239 100644 --- a/td/telegram/RecentDialogList.h +++ b/td/telegram/RecentDialogList.h @@ -9,7 +9,7 @@ #include "td/telegram/DialogId.h" #include "td/actor/actor.h" -#include "td/actor/MultiPromise.h" +#include "td/actor/PromiseFuture.h" #include "td/utils/common.h" @@ -40,11 +40,13 @@ class RecentDialogList : public Actor { vector dialog_ids_; std::unordered_set removed_dialog_ids_; - int32 dialogs_loaded_ = 0; // 0 - not loaded, 1 - load request was sent, 2 - loaded - MultiPromiseActor resolve_dialogs_multipromise_{"ResolveDialogsMultiPromiseActor"}; + bool is_loaded_ = false; + vector> load_list_queries_; void load_dialogs(Promise &&promise); + void on_load_dialogs(vector &&found_dialogs); + bool do_add_dialog(DialogId dialog_id); string get_binlog_key() const;