From 07f4d0d94ee3c0c762aab9199772479f87844d03 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 28 Nov 2018 20:18:50 +0300 Subject: [PATCH] Add notification_id field to message database. GitOrigin-RevId: 036e3fb02d7d18c04f568495ae50be9614717a0f --- benchmark/bench_tddb.cpp | 3 +- td/telegram/DialogDb.cpp | 9 +++--- td/telegram/MessagesDb.cpp | 43 +++++++++++++++++++++-------- td/telegram/MessagesDb.h | 5 ++-- td/telegram/MessagesManager.cpp | 49 ++++++++++++++++----------------- td/telegram/MessagesManager.h | 4 +-- td/telegram/Version.h | 2 +- 7 files changed, 68 insertions(+), 47 deletions(-) diff --git a/benchmark/bench_tddb.cpp b/benchmark/bench_tddb.cpp index 2b110126..1313ce0a 100644 --- a/benchmark/bench_tddb.cpp +++ b/benchmark/bench_tddb.cpp @@ -7,6 +7,7 @@ #include "td/telegram/DialogId.h" #include "td/telegram/MessageId.h" #include "td/telegram/MessagesDb.h" +#include "td/telegram/NotificationId.h" #include "td/telegram/UserId.h" #include "td/actor/actor.h" @@ -57,7 +58,7 @@ class MessagesDbBench : public Benchmark { // use async on same thread. messages_db_async_->add_message({dialog_id, message_id}, unique_message_id, sender_user_id, random_id, - ttl_expires_at, 0, 0, "", std::move(data), Promise<>()); + ttl_expires_at, 0, 0, "", NotificationId(), std::move(data), Promise<>()); } } } diff --git a/td/telegram/DialogDb.cpp b/td/telegram/DialogDb.cpp index 94a7be33..55ddbcaa 100644 --- a/td/telegram/DialogDb.cpp +++ b/td/telegram/DialogDb.cpp @@ -23,7 +23,7 @@ namespace td { // NB: must happen inside a transaction Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) { - LOG(INFO) << "Init dialog db " << tag("version", version); + LOG(INFO) << "Init dialog database " << tag("version", version); was_created = false; // Check if database exists @@ -50,7 +50,7 @@ Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) { }; if (version == 0) { - LOG(INFO) << "Create new dialog db"; + LOG(INFO) << "Create new dialog database"; was_created = true; TRY_STATUS( db.exec("CREATE TABLE IF NOT EXISTS dialogs (dialog_id INT8 PRIMARY KEY, dialog_order INT8, data BLOB, " @@ -60,7 +60,7 @@ Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) { TRY_STATUS(create_notification_group_id_index()); version = current_db_version(); } - if (version < static_cast(DbVersion::DialogDbLastNotificationDate)) { + if (version < static_cast(DbVersion::AddNotificationsSupport)) { TRY_STATUS(db.exec("ALTER TABLE dialogs ADD COLUMN last_notification_date INT4")); TRY_STATUS(db.exec("ALTER TABLE dialogs ADD COLUMN notification_group_id INT4")); TRY_STATUS(create_last_notification_date_index()); @@ -276,7 +276,8 @@ class DialogDbAsync : public DialogDbAsyncInterface { send_closure_later(impl_, &Impl::get_dialogs_by_last_notification_date, last_notification_date, dialog_id, limit, std::move(promise)); } - void get_dialog_by_notification_group_id(NotificationGroupId notification_group_id, Promise promise) override { + void get_dialog_by_notification_group_id(NotificationGroupId notification_group_id, + Promise promise) override { send_closure_later(impl_, &Impl::get_dialog_by_notification_group_id, notification_group_id, std::move(promise)); } void close(Promise<> promise) override { diff --git a/td/telegram/MessagesDb.cpp b/td/telegram/MessagesDb.cpp index c1ae707e..25533f75 100644 --- a/td/telegram/MessagesDb.cpp +++ b/td/telegram/MessagesDb.cpp @@ -40,7 +40,7 @@ static constexpr int32 MESSAGES_DB_INDEX_COUNT_OLD = 9; // NB: must happen inside a transaction Status init_messages_db(SqliteDb &db, int32 version) { - LOG(INFO) << "Init message db " << tag("version", version); + LOG(INFO) << "Init message database " << tag("version", version); // Check if database exists TRY_RESULT(has_table, db.has_table("messages")); @@ -92,18 +92,25 @@ Status init_messages_db(SqliteDb &db, int32 version) { } return Status::OK(); }; + auto add_notification_id_index = [&db]() { + TRY_STATUS( + db.exec("CREATE INDEX IF NOT EXISTS message_by_notification_id ON messages (dialog_id, notification_id) " + "WHERE notification_id IS NOT NULL")); + return Status::OK(); + }; if (version == 0) { - LOG(INFO) << "Create new messages db"; + LOG(INFO) << "Create new message database"; TRY_STATUS( db.exec("CREATE TABLE IF NOT EXISTS messages (dialog_id INT8, message_id INT8, " "unique_message_id INT4, sender_user_id INT4, random_id INT8, data BLOB, " - "ttl_expires_at INT4, index_mask INT4, search_id INT8, text STRING, PRIMARY KEY " + "ttl_expires_at INT4, index_mask INT4, search_id INT8, text STRING, notification_id INT4, PRIMARY KEY " "(dialog_id, message_id))")); TRY_STATUS( db.exec("CREATE INDEX IF NOT EXISTS message_by_random_id ON messages (dialog_id, random_id) " "WHERE random_id IS NOT NULL")); + TRY_STATUS( db.exec("CREATE INDEX IF NOT EXISTS message_by_unique_message_id ON messages " "(unique_message_id) WHERE unique_message_id IS NOT NULL")); @@ -118,6 +125,8 @@ Status init_messages_db(SqliteDb &db, int32 version) { TRY_STATUS(add_call_index()); + TRY_STATUS(add_notification_id_index()); + version = current_db_version(); } if (version < static_cast(DbVersion::MessagesDbMediaIndex)) { @@ -135,12 +144,17 @@ Status init_messages_db(SqliteDb &db, int32 version) { if (version < static_cast(DbVersion::MessagesCallIndex)) { TRY_STATUS(add_call_index()); } + if (version < static_cast(DbVersion::AddNotificationsSupport)) { + TRY_STATUS(db.exec("ALTER TABLE messages ADD COLUMN notification_id INT4")); + TRY_STATUS(add_notification_id_index()); + } return Status::OK(); } // NB: must happen inside a transaction Status drop_messages_db(SqliteDb &db, int32 version) { - LOG(WARNING) << "Drop messages db " << tag("version", version) << tag("current_db_version", current_db_version()); + LOG(WARNING) << "Drop message database " << tag("version", version) + << tag("current_db_version", current_db_version()); return db.exec("DROP TABLE IF EXISTS messages"); } @@ -151,8 +165,9 @@ class MessagesDbImpl : public MessagesDbSyncInterface { } Status init() { - TRY_RESULT(add_message_stmt, - db_.get_statement("INSERT OR REPLACE INTO messages VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)")); + TRY_RESULT( + add_message_stmt, + db_.get_statement("INSERT OR REPLACE INTO messages VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)")); TRY_RESULT(delete_message_stmt, db_.get_statement("DELETE FROM messages WHERE dialog_id = ?1 AND message_id = ?2")); TRY_RESULT(delete_all_dialog_messages_stmt, db_.get_statement("DELETE FROM messages WHERE dialog_id = ?1 AND message_id <= ?2")); @@ -243,7 +258,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface { Status add_message(FullMessageId full_message_id, ServerMessageId unique_message_id, UserId sender_user_id, int64 random_id, int32 ttl_expires_at, int32 index_mask, int64 search_id, string text, - BufferSlice data) override { + NotificationId notification_id, BufferSlice data) override { LOG(INFO) << "Add " << full_message_id << " to database"; auto dialog_id = full_message_id.get_dialog_id(); auto message_id = full_message_id.get_message_id(); @@ -306,6 +321,11 @@ class MessagesDbImpl : public MessagesDbSyncInterface { } else { add_message_stmt_.bind_null(10).ensure(); } + if (notification_id.is_valid()) { + add_message_stmt_.bind_int32(11, notification_id.get()).ensure(); + } else { + add_message_stmt_.bind_null(11).ensure(); + } add_message_stmt_.step().ensure(); @@ -820,9 +840,10 @@ class MessagesDbAsync : public MessagesDbAsyncInterface { void add_message(FullMessageId full_message_id, ServerMessageId unique_message_id, UserId sender_user_id, int64 random_id, int32 ttl_expires_at, int32 index_mask, int64 search_id, string text, - BufferSlice data, Promise<> promise) override { + NotificationId notification_id, BufferSlice data, Promise<> promise) override { send_closure_later(impl_, &Impl::add_message, full_message_id, unique_message_id, sender_user_id, random_id, - ttl_expires_at, index_mask, search_id, std::move(text), std::move(data), std::move(promise)); + ttl_expires_at, index_mask, search_id, std::move(text), notification_id, std::move(data), + std::move(promise)); } void delete_message(FullMessageId full_message_id, Promise<> promise) override { @@ -881,11 +902,11 @@ class MessagesDbAsync : public MessagesDbAsyncInterface { } void add_message(FullMessageId full_message_id, ServerMessageId unique_message_id, UserId sender_user_id, int64 random_id, int32 ttl_expires_at, int32 index_mask, int64 search_id, string text, - BufferSlice data, Promise<> promise) { + NotificationId notification_id, BufferSlice data, Promise<> promise) { add_write_query([=, promise = std::move(promise), data = std::move(data), text = std::move(text)](Unit) mutable { promise.set_result(sync_db_->add_message(full_message_id, unique_message_id, sender_user_id, random_id, ttl_expires_at, index_mask, search_id, std::move(text), - std::move(data))); + notification_id, std::move(data))); }); } diff --git a/td/telegram/MessagesDb.h b/td/telegram/MessagesDb.h index 2200773a..2f780bd5 100644 --- a/td/telegram/MessagesDb.h +++ b/td/telegram/MessagesDb.h @@ -8,6 +8,7 @@ #include "td/telegram/DialogId.h" #include "td/telegram/MessageId.h" +#include "td/telegram/NotificationId.h" #include "td/actor/PromiseFuture.h" @@ -91,7 +92,7 @@ class MessagesDbSyncInterface { virtual Status add_message(FullMessageId full_message_id, ServerMessageId unique_message_id, UserId sender_user_id, int64 random_id, int32 ttl_expires_at, int32 index_mask, int64 search_id, string text, - BufferSlice data) = 0; + NotificationId notification_id, BufferSlice data) = 0; virtual Status delete_message(FullMessageId full_message_id) = 0; virtual Status delete_all_dialog_messages(DialogId dialog_id, MessageId from_message_id) = 0; @@ -134,7 +135,7 @@ class MessagesDbAsyncInterface { virtual void add_message(FullMessageId full_message_id, ServerMessageId unique_message_id, UserId sender_user_id, int64 random_id, int32 ttl_expires_at, int32 index_mask, int64 search_id, string text, - BufferSlice data, Promise<> promise) = 0; + NotificationId notification_id, BufferSlice data, Promise<> promise) = 0; virtual void delete_message(FullMessageId full_message_id, Promise<> promise) = 0; virtual void delete_all_dialog_messages(DialogId dialog_id, MessageId from_message_id, Promise<> promise) = 0; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7fe748a3..ed9fff38 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -5054,7 +5054,7 @@ void MessagesManager::on_update_message_views(FullMessageId full_message_id, int } if (update_message_views(full_message_id.get_dialog_id(), m, views)) { - on_message_changed(d, m, "on_update_message_views"); + on_message_changed(d, m, true, "on_update_message_views"); } } @@ -7832,7 +7832,7 @@ void MessagesManager::read_all_dialog_mentions(DialogId dialog_id, Promise send_closure(G()->td(), &Td::send_update, make_tl_object(dialog_id.get(), m->message_id.get(), 0)); is_update_sent = true; - on_message_changed(d, m, "read_all_mentions"); + on_message_changed(d, m, true, "read_all_mentions"); } if (d->unread_mention_count != 0) { @@ -7917,7 +7917,7 @@ bool MessagesManager::read_message_content(Dialog *d, Message *m, bool is_local_ update_opened_message_content(m->content.get()) | ttl_on_open(d, m, Time::now(), is_local_read); if (is_mention_read || is_content_read) { - on_message_changed(d, m, "read_message_content"); + on_message_changed(d, m, true, "read_message_content"); if (is_content_read) { send_closure(G()->td(), &Td::send_update, make_tl_object(d->dialog_id.get(), m->message_id.get())); @@ -8459,7 +8459,7 @@ void MessagesManager::ttl_on_view(const Dialog *d, Message *message, double view !message->is_failed_to_send && !message->is_content_secret) { message->ttl_expires_at = message->ttl + view_date; ttl_register_message(d->dialog_id, message, now); - on_message_changed(d, message, "ttl_on_view"); + on_message_changed(d, message, true, "ttl_on_view"); } } @@ -8518,7 +8518,7 @@ void MessagesManager::ttl_loop(double now) { auto m = get_message(d, full_message_id.get_message_id()); CHECK(m != nullptr); on_message_ttl_expired(d, m); - on_message_changed(d, m, "ttl_loop"); + on_message_changed(d, m, true, "ttl_loop"); } } for (auto &it : to_delete) { @@ -9915,7 +9915,7 @@ void MessagesManager::on_update_message_web_page(FullMessageId full_message_id, set_message_content_web_page_id(content, WebPageId()); // don't need to send an update - on_message_changed(d, message, "on_update_message_web_page"); + on_message_changed(d, message, true, "on_update_message_web_page"); return; } @@ -11433,7 +11433,7 @@ Status MessagesManager::delete_dialog_reply_markup(DialogId dialog_id, MessageId message->reply_markup->is_personal = false; set_dialog_reply_markup(d, message_id); - on_message_changed(d, message, "delete_dialog_reply_markup"); + on_message_changed(d, message, true, "delete_dialog_reply_markup"); } } else { // non-bots can't have messages with RemoveKeyboard @@ -12161,7 +12161,7 @@ Status MessagesManager::view_messages(DialogId dialog_id, const vectorserver_unread_count + d->local_unread_count; // TODO remove/add some messages with unread mentions } -void MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool force) { +bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool force) { CHECK(d != nullptr); CHECK(m != nullptr); CHECK(!m->notification_id.is_valid()); if (m->is_outgoing || d->dialog_id == get_my_dialog_id() || td_->auth_manager_->is_bot()) { - return; + return false; } if (m->message_id.get() <= d->last_read_inbox_message_id.get()) { VLOG(notifications) << "Disable notification for read " << m->message_id << " in " << d->dialog_id; - return; + return false; } if (d->dialog_id.get_type() == DialogType::Channel) { if (!td_->contacts_manager_->get_channel_status(d->dialog_id.get_channel_id()).is_member() || m->date < td_->contacts_manager_->get_channel_date(d->dialog_id.get_channel_id())) { - return; + return false; } } @@ -17509,7 +17509,7 @@ void MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f std::tie(have_settings, mute_until) = get_dialog_mute_until(settings_dialog_id, settings_dialog); if (mute_until > G()->unix_time()) { VLOG(notifications) << "Disable notification, because " << settings_dialog_id << " is muted"; - return; + return false; } if (!force && (!have_settings || !d->pending_new_message_notifications.empty())) { @@ -17543,7 +17543,7 @@ void MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f send_get_dialog_query(settings_dialog_id, std::move(promise)); } } - return; + return false; } LOG_IF(WARNING, !have_settings) << "Have no notification settings for " << settings_dialog_id @@ -17555,6 +17555,7 @@ void MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f send_closure_later(G()->notification_manager(), &NotificationManager::add_notification, get_dialog_message_notification_group_id(d), d->dialog_id, m->date, settings_dialog_id, m->disable_notification, m->notification_id, create_new_message_notification(m->message_id)); + return true; } void MessagesManager::flush_pending_new_message_notifications(DialogId dialog_id, DialogId settings_dialog_id) { @@ -17575,7 +17576,9 @@ void MessagesManager::flush_pending_new_message_notifications(DialogId dialog_id while (it != d->pending_new_message_notifications.end() && it->first == DialogId()) { auto m = get_message(d, it->second); if (m != nullptr) { - add_new_message_notification(d, m, true); + if (add_new_message_notification(d, m, true)) { + on_message_changed(d, m, false, "flush_pending_new_message_notifications"); + } } ++it; } @@ -20521,10 +20524,10 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq return result_message; } -void MessagesManager::on_message_changed(const Dialog *d, const Message *m, const char *source) { +void MessagesManager::on_message_changed(const Dialog *d, const Message *m, bool need_send_update, const char *source) { CHECK(d != nullptr); CHECK(m != nullptr); - if (m->message_id == d->last_message_id) { + if (need_send_update && m->message_id == d->last_message_id) { send_update_chat_last_message_impl(d, source); } @@ -20585,7 +20588,8 @@ void MessagesManager::add_message_to_database(const Dialog *d, const Message *m, } G()->td_db()->get_messages_db_async()->add_message({d->dialog_id, message_id}, unique_message_id, m->sender_user_id, random_id, ttl_expires_at, get_message_index_mask(d->dialog_id, m), - search_id, text, log_event_store(*m), Auto()); // TODO Promise + search_id, text, m->notification_id, log_event_store(*m), + Auto()); // TODO Promise } void MessagesManager::delete_all_dialog_messages_from_database(const Dialog *d, MessageId message_id, @@ -20994,14 +20998,7 @@ void MessagesManager::update_message(Dialog *d, unique_ptr &old_message send_update_message_edited(dialog_id, old_message.get()); } - if (is_changed) { - on_message_changed(d, old_message.get(), "update_message"); - } else { - // need to save message always, because it might be added to some message index - if (!message_id.is_yet_unsent()) { - add_message_to_database(d, old_message.get(), "update_message"); - } - } + on_message_changed(d, old_message.get(), is_changed, "update_message"); } bool MessagesManager::need_message_changed_warning(const Message *old_message) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 704e2bb8..8d22600d 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1430,7 +1430,7 @@ class MessagesManager : public Actor { Message *add_message_to_dialog(Dialog *d, unique_ptr message, bool from_update, bool *need_update, bool *need_update_dialog_pos, const char *source); - void on_message_changed(const Dialog *d, const Message *m, const char *source); + void on_message_changed(const Dialog *d, const Message *m, bool need_send_update, const char *source); void add_message_to_database(const Dialog *d, const Message *m, const char *source); @@ -1465,7 +1465,7 @@ class MessagesManager : public Actor { int32 get_dialog_pending_notification_count(Dialog *d); - void add_new_message_notification(Dialog *d, Message *m, bool force); + bool add_new_message_notification(Dialog *d, Message *m, bool force); void flush_pending_new_message_notifications(DialogId dialog_id, DialogId settings_dialog_id); diff --git a/td/telegram/Version.h b/td/telegram/Version.h index efc564e7..5c2582a3 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -36,7 +36,7 @@ enum class DbVersion : int32 { MessagesDbFts, MessagesCallIndex, FixFileRemoteLocationKeyBug, - DialogDbLastNotificationDate, + AddNotificationsSupport, Next };