summary refs log tree commit diff
path: root/src/Cache.cpp
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2022-06-15 02:13:17 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2022-06-15 02:13:17 +0200
commitef9ebe3fd33a9596c5395860fcfaad1d02535f91 (patch)
tree4a74f4e4ee9a3aadc430453e9e78ce481fc1552b /src/Cache.cpp
parentUpdate hidden read receipts MSC (diff)
downloadnheko-ef9ebe3fd33a9596c5395860fcfaad1d02535f91.tar.xz
Speedup startup by caching last message timestamp
The cache is only approximate, i.e. it doesn't skip edits and similar,
but this might be good enough? Also no migration right now.

Speeds up startup by about 5x on my system.

Half the startup time is now loading the powerlevels for each room. We
can probably lazily load those too in the future.
Diffstat (limited to 'src/Cache.cpp')
-rw-r--r--src/Cache.cpp88
1 files changed, 72 insertions, 16 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 90c04e61..2b83fbb5 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -1570,6 +1570,47 @@ Cache::updateState(const std::string &room, const mtx::responses::StateEvents &s
     txn.commit();
 }
 
+namespace {
+template<typename T>
+auto
+isMessage(const mtx::events::RoomEvent<T> &e)
+  -> std::enable_if_t<std::is_same<decltype(e.content.msgtype), std::string>::value, bool>
+{
+    return true;
+}
+
+template<typename T>
+auto
+isMessage(const mtx::events::Event<T> &)
+{
+    return false;
+}
+
+template<typename T>
+auto
+isMessage(const mtx::events::EncryptedEvent<T> &)
+{
+    return true;
+}
+
+auto
+isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &)
+{
+    return true;
+}
+
+auto
+isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &)
+{
+    return true;
+}
+auto
+isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &)
+{
+    return true;
+}
+}
+
 void
 Cache::saveState(const mtx::responses::Sync &res)
 {
@@ -1623,6 +1664,25 @@ Cache::saveState(const mtx::responses::Sync &res)
         saveTimelineMessages(txn, eventsDb, room.first, room.second.timeline);
 
         RoomInfo updatedInfo;
+        {
+            // retrieve the old tags and modification ts
+            std::string_view data;
+            if (roomsDb_.get(txn, room.first, data)) {
+                try {
+                    RoomInfo tmp     = json::parse(std::string_view(data.data(), data.size()));
+                    updatedInfo.tags = std::move(tmp.tags);
+
+                    updatedInfo.approximate_last_modification_ts =
+                      tmp.approximate_last_modification_ts;
+                } catch (const json::exception &e) {
+                    nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
+                                      room.first,
+                                      std::string(data.data(), data.size()),
+                                      e.what());
+                }
+            }
+        }
+
         updatedInfo.name       = getRoomName(txn, statesdb, membersdb).toStdString();
         updatedInfo.topic      = getRoomTopic(txn, statesdb).toStdString();
         updatedInfo.avatar_url = getRoomAvatarUrl(txn, statesdb, membersdb).toStdString();
@@ -1666,7 +1726,6 @@ Cache::saveState(const mtx::responses::Sync &res)
                 rooms_with_space_updates.insert(room.first);
         }
 
-        bool has_new_tags = false;
         // Process the account_data associated with this room
         if (!room.second.account_data.events.empty()) {
             auto accountDataDb = getAccountDataDb(txn, room.first);
@@ -1691,7 +1750,8 @@ Cache::saveState(const mtx::responses::Sync &res)
                 // for tag events
                 if (std::holds_alternative<AccountDataEvent<account_data::Tags>>(evt)) {
                     auto tags_evt = std::get<AccountDataEvent<account_data::Tags>>(evt);
-                    has_new_tags  = true;
+
+                    updatedInfo.tags.clear();
                     for (const auto &tag : tags_evt.content.tags) {
                         updatedInfo.tags.push_back(tag.first);
                     }
@@ -1704,20 +1764,12 @@ Cache::saveState(const mtx::responses::Sync &res)
                 }
             }
         }
-        if (!has_new_tags) {
-            // retrieve the old tags, they haven't changed
-            std::string_view data;
-            if (roomsDb_.get(txn, room.first, data)) {
-                try {
-                    RoomInfo tmp     = json::parse(std::string_view(data.data(), data.size()));
-                    updatedInfo.tags = tmp.tags;
-                } catch (const json::exception &e) {
-                    nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
-                                      room.first,
-                                      std::string(data.data(), data.size()),
-                                      e.what());
-                }
-            }
+
+        for (const auto &e : room.second.timeline.events) {
+            if (!std::visit([](const auto &e) -> bool { return isMessage(e); }, e))
+                continue;
+            updatedInfo.approximate_last_modification_ts =
+              mtx::accessors::origin_server_ts(e).toMSecsSinceEpoch();
         }
 
         roomsDb_.put(txn, room.first, json(updatedInfo).dump());
@@ -4709,6 +4761,8 @@ to_json(json &j, const RoomInfo &info)
     j["join_rule"]    = info.join_rule;
     j["guest_access"] = info.guest_access;
 
+    j["app_l_ts"] = info.approximate_last_modification_ts;
+
     j["notification_count"] = info.notification_count;
     j["highlight_count"]    = info.highlight_count;
 
@@ -4732,6 +4786,8 @@ from_json(const json &j, RoomInfo &info)
     info.join_rule    = j.at("join_rule");
     info.guest_access = j.at("guest_access");
 
+    info.approximate_last_modification_ts = j.value("app_l_ts", 0);
+
     info.notification_count = j.value("notification_count", 0);
     info.highlight_count    = j.value("highlight_count", 0);