diff --git a/td/telegram/MessagesDb.cpp b/td/telegram/MessagesDb.cpp index 6d6563903..da104be1a 100644 --- a/td/telegram/MessagesDb.cpp +++ b/td/telegram/MessagesDb.cpp @@ -526,7 +526,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface { return std::make_pair(std::move(messages), next_expire_till); } - Result get_messages(MessagesDbMessagesQuery query) override { + Result> get_messages(MessagesDbMessagesQuery query) override { if (query.index_mask != 0) { return get_messages_from_index(query.dialog_id, query.from_message_id, query.index_mask, query.offset, query.limit); @@ -657,7 +657,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface { return std::move(result); } - Result get_messages_from_index(DialogId dialog_id, MessageId from_message_id, + Result> get_messages_from_index(DialogId dialog_id, MessageId from_message_id, int32 index_mask, int32 offset, int32 limit) { CHECK(index_mask != 0); CHECK(index_mask < (1 << MESSAGES_DB_INDEX_COUNT)) << tag("index_mask", index_mask); @@ -751,7 +751,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface { SqliteStatement get_messages_fts_stmt_; - Result get_messages_impl(GetMessagesStmt &stmt, DialogId dialog_id, + Result> get_messages_impl(GetMessagesStmt &stmt, DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit) { CHECK(dialog_id.is_valid()) << dialog_id; CHECK(from_message_id.is_valid()); @@ -790,16 +790,16 @@ class MessagesDbImpl : public MessagesDbSyncInterface { std::reverse(right.begin(), right.end()); } if (left.empty()) { - return MessagesDbMessagesResult{std::move(right)}; + return std::move(right); } if (right.empty()) { - return MessagesDbMessagesResult{std::move(left)}; + return std::move(left); } right.reserve(right.size() + left.size()); std::move(left.begin(), left.end(), std::back_inserter(right)); - return MessagesDbMessagesResult{std::move(right)}; + return std::move(right); } Result> get_messages_inner(SqliteStatement &stmt, int64 dialog_id, int64 from_message_id, @@ -900,7 +900,7 @@ class MessagesDbAsync : public MessagesDbAsyncInterface { std::move(promise)); } - void get_messages(MessagesDbMessagesQuery query, Promise promise) override { + void get_messages(MessagesDbMessagesQuery query, Promise> promise) override { send_closure_later(impl_, &Impl::get_messages, std::move(query), std::move(promise)); } void get_messages_from_notification_id(DialogId dialog_id, NotificationId from_notification_id, int32 limit, @@ -976,7 +976,7 @@ class MessagesDbAsync : public MessagesDbAsyncInterface { promise.set_result(sync_db_->get_dialog_message_by_date(dialog_id, first_message_id, last_message_id, date)); } - void get_messages(MessagesDbMessagesQuery query, Promise promise) { + void get_messages(MessagesDbMessagesQuery query, Promise> promise) { add_read_query(); promise.set_result(sync_db_->get_messages(std::move(query))); } diff --git a/td/telegram/MessagesDb.h b/td/telegram/MessagesDb.h index 758799748..ef2013490 100644 --- a/td/telegram/MessagesDb.h +++ b/td/telegram/MessagesDb.h @@ -53,10 +53,6 @@ struct MessagesDbMessagesQuery { int32 limit{100}; }; -struct MessagesDbMessagesResult { - std::vector messages; -}; - struct MessagesDbMessage { DialogId dialog_id; BufferSlice data; @@ -105,7 +101,7 @@ class MessagesDbSyncInterface { virtual Result get_dialog_message_by_date(DialogId dialog_id, MessageId first_message_id, MessageId last_message_id, int32 date) = 0; - virtual Result get_messages(MessagesDbMessagesQuery query) = 0; + virtual Result> get_messages(MessagesDbMessagesQuery query) = 0; virtual Result> get_messages_from_notification_id(DialogId dialog_id, NotificationId from_notification_id, int32 limit) = 0; @@ -151,7 +147,7 @@ class MessagesDbAsyncInterface { virtual void get_dialog_message_by_date(DialogId dialog_id, MessageId first_message_id, MessageId last_message_id, int32 date, Promise promise) = 0; - virtual void get_messages(MessagesDbMessagesQuery query, Promise promise) = 0; + virtual void get_messages(MessagesDbMessagesQuery query, Promise> promise) = 0; virtual void get_messages_from_notification_id(DialogId dialog_id, NotificationId from_notification_id, int32 limit, Promise> promise) = 0; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ee6d15bb7..0a46d3181 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -13287,10 +13287,10 @@ std::pair> MessagesManager::search_dialog_messages( << " and with limit " << limit; auto new_promise = PromiseCreator::lambda( [random_id, dialog_id, fixed_from_message_id, first_db_message_id, filter_type, offset, limit, - promise = std::move(promise)](Result result) mutable { + promise = std::move(promise)](Result> r_messages) mutable { send_closure(G()->messages_manager(), &MessagesManager::on_search_dialog_messages_db_result, random_id, dialog_id, fixed_from_message_id, first_db_message_id, filter_type, offset, limit, - std::move(result), std::move(promise)); + std::move(r_messages), std::move(promise)); }); MessagesDbMessagesQuery db_query; db_query.dialog_id = dialog_id; @@ -13597,16 +13597,17 @@ MessageId MessagesManager::get_first_database_message_id_by_index(const Dialog * void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id, MessageId first_db_message_id, SearchMessagesFilter filter_type, int32 offset, int32 limit, - Result result, Promise<> promise) { - if (result.is_error()) { - LOG(ERROR) << result.error(); + Result> r_messages, + Promise<> promise) { + if (r_messages.is_error()) { + LOG(ERROR) << r_messages.error(); if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat) { found_dialog_messages_.erase(random_id); } return promise.set_value(Unit()); } - auto messages = result.move_as_ok().messages; + auto messages = r_messages.move_as_ok(); Dialog *d = get_dialog(dialog_id); CHECK(d != nullptr); @@ -14246,9 +14247,9 @@ void MessagesManager::get_history_from_the_end(DialogId dialog_id, bool from_dat db_query.limit = limit; G()->td_db()->get_messages_db_async()->get_messages( db_query, PromiseCreator::lambda([dialog_id, only_local, limit, actor_id = actor_id(this), - promise = std::move(promise)](MessagesDbMessagesResult result) mutable { + promise = std::move(promise)](std::vector messages) mutable { send_closure(actor_id, &MessagesManager::on_get_history_from_database, dialog_id, MessageId::max(), 0, limit, - true, only_local, std::move(result.messages), std::move(promise)); + true, only_local, std::move(messages), std::move(promise)); })); } else { if (only_local || dialog_id.get_type() == DialogType::SecretChat) { @@ -14279,9 +14280,9 @@ void MessagesManager::get_history(DialogId dialog_id, MessageId from_message_id, G()->td_db()->get_messages_db_async()->get_messages( db_query, PromiseCreator::lambda([dialog_id, from_message_id, offset, limit, only_local, actor_id = actor_id(this), - promise = std::move(promise)](MessagesDbMessagesResult result) mutable { + promise = std::move(promise)](std::vector messages) mutable { send_closure(actor_id, &MessagesManager::on_get_history_from_database, dialog_id, from_message_id, offset, - limit, false, only_local, std::move(result.messages), std::move(promise)); + limit, false, only_local, std::move(messages), std::move(promise)); })); } else { if (only_local || dialog_id.get_type() == DialogType::SecretChat) { @@ -17696,7 +17697,7 @@ MessagesManager::MessageNotificationGroup MessagesManager::get_message_notificat create_new_secret_chat_notification()); } else { result.notifications = get_message_notifications_from_database_force( - d, NotificationId::max(), static_cast(td_->notification_manager_->get_max_notification_group_size())); + d, static_cast(td_->notification_manager_->get_max_notification_group_size())); } int32 last_notification_date = 0; @@ -17724,17 +17725,16 @@ bool MessagesManager::is_message_has_active_notification(const Dialog *d, const (m->message_id.get() > d->last_read_inbox_message_id.get() || m->contains_unread_mention); } -vector MessagesManager::get_message_notifications_from_database_force(Dialog *d, - NotificationId from_notification_id, - int32 limit) { +vector MessagesManager::get_message_notifications_from_database_force(Dialog *d, int32 limit) { CHECK(d != nullptr); if (!G()->parameters().use_message_db) { return {}; } + auto from_notification_id = NotificationId::max(); + auto from_message_id = MessageId::max(); while (true) { - auto result = G()->td_db()->get_messages_db_sync()->get_messages_from_notification_id(d->dialog_id, - from_notification_id, limit); + auto result = do_get_message_notifications_from_database_force(d, from_notification_id, from_message_id, limit); if (result.is_error()) { return {}; } @@ -17749,11 +17749,15 @@ vector MessagesManager::get_message_notifications_from_database_fo VLOG(notifications) << "Loaded " << messages.size() << " messages with notifications from database"; for (auto &message : messages) { auto m = on_get_message_from_database(d->dialog_id, d, std::move(message)); + if (m == nullptr || !m->notification_id.is_valid()) { + // notification_id can be empty if it is deleted in memory, but not in the database + continue; + } + if (is_message_has_active_notification(d, m)) { res.emplace_back(m->notification_id, m->date, create_new_message_notification(m->message_id)); - } else if (m != nullptr && m->notification_id.is_valid() && - (m->notification_id.get() <= d->max_removed_notification_id.get() || - (m->message_id.get() <= d->last_read_inbox_message_id.get() && d->unread_mention_count == 0))) { + } else if (m->notification_id.get() <= d->max_removed_notification_id.get() || + (m->message_id.get() <= d->last_read_inbox_message_id.get() && d->unread_mention_count == 0)) { // if message still has notification_id, but it was removed via max_removed_notification_id // or last_read_inbox_message_id, then there will be no more messages with active notifications @@ -17762,11 +17766,11 @@ vector MessagesManager::get_message_notifications_from_database_fo is_found = false; break; } - if (m != nullptr && m->notification_id.is_valid()) { - CHECK(m->notification_id.get() < from_notification_id.get()); - from_notification_id = m->notification_id; - is_found = true; - } + + CHECK(m->notification_id.get() < from_notification_id.get()); + from_notification_id = m->notification_id; + from_message_id = m->message_id; + is_found = true; } if (!res.empty() || !is_found) { return res; @@ -17774,6 +17778,38 @@ vector MessagesManager::get_message_notifications_from_database_fo } } +Result> MessagesManager::do_get_message_notifications_from_database_force( + Dialog *d, NotificationId from_notification_id, MessageId from_message_id, int32 limit) { + CHECK(G()->parameters().use_message_db); + + if (from_notification_id.get() <= d->max_removed_notification_id.get()) { + return vector(); + } + + auto db = G()->td_db()->get_messages_db_sync(); + if (!is_dialog_muted(d) && from_message_id.get() > d->last_read_inbox_message_id.get()) { + // there are some notifications with unread messages + VLOG(notifications) << "Trying to load " << limit << " messages with notifications in " << d->dialog_id << " from " + << from_notification_id; + return db->get_messages_from_notification_id(d->dialog_id, from_notification_id, limit); + } + if (d->unread_mention_count == 0) { + return vector(); + } + + VLOG(notifications) << "Trying to load " << limit << " messages with unread mentions in " << d->dialog_id << " from " + << from_message_id; + + // ignore first_db_message_id, notifications can be nonconsecutive + MessagesDbMessagesQuery db_query; + db_query.dialog_id = d->dialog_id; + db_query.index_mask = search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); + db_query.from_message_id = from_message_id; + db_query.offset = 0; + db_query.limit = limit; + return db->get_messages(db_query); +} + vector MessagesManager::get_message_notification_group_keys_from_database( int32 from_last_notification_date, DialogId from_dialog_id, int32 limit) { if (!G()->parameters().use_message_db) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 079d5de58..1f8958169 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1501,8 +1501,11 @@ class MessagesManager : public Actor { NotificationId get_next_notification_id(Dialog *d, MessageId message_id); - vector get_message_notifications_from_database_force(Dialog *d, NotificationId from_notification_id, - int32 limit); + vector get_message_notifications_from_database_force(Dialog *d, int32 limit); + + Result> do_get_message_notifications_from_database_force(Dialog *d, + NotificationId from_notification_id, + MessageId from_message_id, int32 limit); void on_get_message_notifications_from_database(DialogId dialog_id, int32 limit, Result> result, Promise> promise); @@ -1755,7 +1758,7 @@ class MessagesManager : public Actor { void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id, MessageId first_db_message_id, SearchMessagesFilter filter_type, - int32 offset, int32 limit, Result result, + int32 offset, int32 limit, Result> r_messages, Promise<> promise); void on_messages_db_fts_result(Result result, int64 random_id, Promise<> &&promise);