From ab99fc7a8d8f5c91193f52a9d8d55d7dd7bfbced Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Sep 2020 16:08:35 +0300 Subject: [PATCH 1/2] Store yet unsent message IDs separately for different threads. GitOrigin-RevId: f68b88a1ea05dcb3096357328635191cae02edcb --- td/telegram/MessagesManager.cpp | 15 +++++++++++++++ td/telegram/MessagesManager.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 4b680e847..a601906dc 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -14391,6 +14391,16 @@ unique_ptr MessagesManager::do_delete_message(Dialog * void MessagesManager::on_message_deleted(Dialog *d, Message *m, bool is_permanently_deleted, const char *source) { // also called for unloaded messages + if (m->message_id.is_yet_unsent() && m->top_thread_message_id.is_valid()) { + auto it = d->yet_unsent_thread_message_ids.find(m->top_thread_message_id); + CHECK(it != d->yet_unsent_thread_message_ids.end()); + auto is_deleted = it->second.erase(m->message_id) > 0; + CHECK(is_deleted); + if (it->second.empty()) { + d->yet_unsent_thread_message_ids.erase(it); + } + } + cancel_send_deleted_message(d->dialog_id, m, is_permanently_deleted); CHECK(m->message_id.is_valid()); @@ -30942,6 +30952,11 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } + if (m->message_id.is_yet_unsent() && m->top_thread_message_id.is_valid()) { + auto is_inserted = d->yet_unsent_thread_message_ids[m->top_thread_message_id].insert(m->message_id).second; + CHECK(is_inserted); + } + switch (dialog_id.get_type()) { case DialogType::User: case DialogType::Chat: diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 7b482df2e..2c2e8b0ff 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1250,6 +1250,9 @@ class MessagesManager : public Actor { // application start, used to guarantee that all assigned message identifiers // are different + std::unordered_map, MessageIdHash> + yet_unsent_thread_message_ids; // top_thread_message_id -> yet unsent message IDs + std::unordered_map scheduled_message_date; std::unordered_map yet_unsent_message_id_to_persistent_message_id; From 7cde6f0adb890300355663f904155570197f8b9d Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 29 Sep 2020 00:22:35 +0300 Subject: [PATCH 2/2] Save local thread message ids. GitOrigin-RevId: d0905e9b8ae4d6bed1d25d6ecc6c159d65dc87cd --- td/telegram/MessagesManager.cpp | 51 +++++++++++++++++++++++++++++++++ td/telegram/MessagesManager.h | 3 ++ 2 files changed, 54 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index a601906dc..6ea90645e 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4495,6 +4495,7 @@ void MessagesManager::Message::store(StorerT &storer) const { bool has_reply_in_dialog_id = is_reply && reply_in_dialog_id.is_valid(); bool has_top_thread_message_id = top_thread_message_id.is_valid(); bool has_thread_draft_message = thread_draft_message != nullptr; + bool has_local_thread_message_ids = !local_thread_message_ids.empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(is_channel_post); STORE_FLAG(is_outgoing); @@ -4549,6 +4550,7 @@ void MessagesManager::Message::store(StorerT &storer) const { STORE_FLAG(has_reply_in_dialog_id); STORE_FLAG(has_top_thread_message_id); STORE_FLAG(has_thread_draft_message); + STORE_FLAG(has_local_thread_message_ids); END_STORE_FLAGS(); } @@ -4645,6 +4647,9 @@ void MessagesManager::Message::store(StorerT &storer) const { if (has_thread_draft_message) { store(thread_draft_message, storer); } + if (has_local_thread_message_ids) { + store(local_thread_message_ids, storer); + } store_message_content(content.get(), storer); if (has_reply_markup) { store(reply_markup, storer); @@ -4684,6 +4689,7 @@ void MessagesManager::Message::parse(ParserT &parser) { bool has_reply_in_dialog_id = false; bool has_top_thread_message_id = false; bool has_thread_draft_message = false; + bool has_local_thread_message_ids = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_channel_post); PARSE_FLAG(is_outgoing); @@ -4738,6 +4744,7 @@ void MessagesManager::Message::parse(ParserT &parser) { PARSE_FLAG(has_reply_in_dialog_id); PARSE_FLAG(has_top_thread_message_id); PARSE_FLAG(has_thread_draft_message); + PARSE_FLAG(has_local_thread_message_ids); END_PARSE_FLAGS(); } @@ -4840,6 +4847,9 @@ void MessagesManager::Message::parse(ParserT &parser) { if (has_thread_draft_message) { parse(thread_draft_message, parser); } + if (has_local_thread_message_ids) { + parse(local_thread_message_ids, parser); + } parse_message_content(content, parser); if (has_reply_markup) { parse(reply_markup, parser); @@ -6190,6 +6200,7 @@ void MessagesManager::on_update_service_notification(tl_object_ptr MessagesManager::add_local_message( auto result = add_message_to_dialog(d, std::move(m), true, &need_update, &need_update_dialog_pos, "add local message"); LOG_CHECK(result != nullptr) << message_id << " " << debug_add_message_to_dialog_fail_reason_; + register_new_local_message_id(d, result); if (is_message_auto_read(dialog_id, result->is_outgoing)) { if (result->is_outgoing) { @@ -27603,6 +27615,7 @@ void MessagesManager::fail_send_message(FullMessageId full_message_id, int error // add_message_to_dialog will not update counts, because need_update == false update_message_count_by_index(d, +1, m); } + register_new_local_message_id(d, m); LOG(INFO) << "Send updateMessageSendFailed for " << full_message_id; if (!td_->auth_manager_->is_bot()) { @@ -31119,6 +31132,30 @@ MessagesManager::Message *MessagesManager::add_scheduled_message_to_dialog(Dialo return result_message; } +void MessagesManager::register_new_local_message_id(Dialog *d, const Message *m) { + if (m == nullptr) { + return; + } + if (m->message_id.is_scheduled()) { + return; + } + CHECK(m->message_id.is_local()); + if (m->top_thread_message_id.is_valid() && m->top_thread_message_id != m->message_id) { + Message *top_m = get_message_force(d, m->top_thread_message_id, "register_new_local_message_id"); + if (top_m != nullptr && top_m->top_thread_message_id == top_m->message_id) { + auto it = std::lower_bound(top_m->local_thread_message_ids.begin(), top_m->local_thread_message_ids.end(), + m->message_id); + if (it == top_m->local_thread_message_ids.end() || *it != m->message_id) { + top_m->local_thread_message_ids.insert(it, m->message_id); + if (top_m->local_thread_message_ids.size() >= 1000) { + top_m->local_thread_message_ids.erase(top_m->local_thread_message_ids.begin()); + } + on_message_changed(d, top_m, false, "register_new_local_message_id"); + } + } + } +} + void MessagesManager::on_message_changed(const Dialog *d, const Message *m, bool need_send_update, const char *source) { CHECK(d != nullptr); CHECK(m != nullptr); @@ -31333,6 +31370,20 @@ void MessagesManager::delete_message_from_database(Dialog *d, MessageId message_ return; } + if (m != nullptr && !m->message_id.is_scheduled() && m->message_id.is_local() && + m->top_thread_message_id.is_valid() && m->top_thread_message_id != m->message_id) { + // must not load the message from the database + Message *top_m = get_message(d, m->top_thread_message_id); + if (top_m != nullptr && top_m->top_thread_message_id == top_m->message_id) { + auto it = std::lower_bound(top_m->local_thread_message_ids.begin(), top_m->local_thread_message_ids.end(), + m->message_id); + if (it != top_m->local_thread_message_ids.end() && *it == m->message_id) { + top_m->local_thread_message_ids.erase(it); + on_message_changed(d, top_m, false, "delete_message_from_database"); + } + } + } + if (is_permanently_deleted) { if (message_id.is_scheduled() && message_id.is_scheduled_server()) { d->deleted_scheduled_server_message_ids.insert(message_id.get_scheduled_server_message_id()); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 2c2e8b0ff..f0c0f7810 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1035,6 +1035,7 @@ class MessagesManager : public Actor { int64 reply_to_random_id = 0; // for send_message DialogId reply_in_dialog_id; MessageId top_thread_message_id; + vector local_thread_message_ids; UserId via_bot_user_id; @@ -2056,6 +2057,8 @@ class MessagesManager : public Actor { Message *add_scheduled_message_to_dialog(Dialog *d, unique_ptr message, bool from_update, bool *need_update, const char *source); + void register_new_local_message_id(Dialog *d, const Message *m); + void on_message_changed(const Dialog *d, const Message *m, bool need_send_update, const char *source); bool need_delete_file(FullMessageId full_message_id, FileId file_id) const;