Load recent dialogs in one pass.
This commit is contained in:
parent
fa65e429eb
commit
55ad2e5f86
@ -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<Unit> &&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<int64>(*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<DialogId> 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<int64>(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<td_api::chats> &&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<string> &&found_dialogs) {
|
||||
auto promises = std::move(load_list_queries_);
|
||||
CHECK(!promises.empty());
|
||||
|
||||
vector<DialogId> 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<int64>(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<int64>(*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<td_api::chats> &&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<Unit>());
|
||||
}
|
||||
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<Unit>());
|
||||
}
|
||||
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<DialogId> 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<int32, vector<DialogId>> RecentDialogList::get_dialogs(int32 limit, Promise<Unit> &&promise) {
|
||||
load_dialogs(std::move(promise));
|
||||
if (dialogs_loaded_ != 2) {
|
||||
if (!is_loaded_) {
|
||||
return {};
|
||||
}
|
||||
|
||||
update_dialogs();
|
||||
|
||||
size_t result_size = min(static_cast<size_t>(limit), dialog_ids_.size());
|
||||
return {narrow_cast<int32>(dialog_ids_.size()),
|
||||
vector<DialogId>(dialog_ids_.begin(), dialog_ids_.begin() + result_size)};
|
||||
CHECK(limit >= 0);
|
||||
int32 total_count = narrow_cast<int32>(dialog_ids_.size());
|
||||
return {total_count, vector<DialogId>(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();
|
||||
|
@ -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<DialogId> dialog_ids_;
|
||||
std::unordered_set<DialogId, DialogIdHash> 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<Promise<Unit>> load_list_queries_;
|
||||
|
||||
void load_dialogs(Promise<Unit> &&promise);
|
||||
|
||||
void on_load_dialogs(vector<string> &&found_dialogs);
|
||||
|
||||
bool do_add_dialog(DialogId dialog_id);
|
||||
|
||||
string get_binlog_key() const;
|
||||
|
Loading…
Reference in New Issue
Block a user