Fix race when reading members from db

This commit is contained in:
Nicolas Werner 2020-11-25 23:43:31 +01:00
parent 7cda502edd
commit c31b9e2793
5 changed files with 52 additions and 29 deletions

View file

@ -1808,6 +1808,17 @@ Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id)
e.what()); e.what());
return {}; return {};
} }
auto membersdb{0};
try {
membersdb = getMembersDb(txn, room_id);
} catch (lmdb::runtime_error &e) {
nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
room_id,
e.what());
return {};
}
if (orderDb.size(txn) == 0) if (orderDb.size(txn) == 0)
return DescInfo{}; return DescInfo{};
@ -1850,9 +1861,16 @@ Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id)
mtx::events::collections::TimelineEvent te; mtx::events::collections::TimelineEvent te;
mtx::events::collections::from_json(obj, te); mtx::events::collections::from_json(obj, te);
lmdb::val info;
MemberInfo m;
if (lmdb::dbi_get(
txn, membersdb, lmdb::val(obj["sender"].get<std::string>()), info)) {
m = json::parse(std::string_view(info.data(), info.size()));
}
cursor.close(); cursor.close();
return utils::getMessageDescription( return utils::getMessageDescription(
te.data, local_user, QString::fromStdString(room_id)); te.data, local_user, QString::fromStdString(m.name));
} }
cursor.close(); cursor.close();
@ -1911,7 +1929,6 @@ Cache::getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersd
// Resolve avatar for 1-1 chats. // Resolve avatar for 1-1 chats.
while (cursor.get(user_id, member_data, MDB_NEXT)) { while (cursor.get(user_id, member_data, MDB_NEXT)) {
try { try {
MemberInfo m = json::parse(member_data); MemberInfo m = json::parse(member_data);
if (user_id == localUserId_.toStdString()) { if (user_id == localUserId_.toStdString()) {

View file

@ -20,7 +20,6 @@
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
#include <QShortcut> #include <QShortcut>
#include <QtConcurrent>
#include <mtx/responses.hpp> #include <mtx/responses.hpp>
@ -281,10 +280,12 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
&ChatPage::setGroupViewState); &ChatPage::setGroupViewState);
connect(this, &ChatPage::initializeRoomList, room_list_, &RoomList::initialize); connect(this, &ChatPage::initializeRoomList, room_list_, &RoomList::initialize);
connect(this, connect(
this,
&ChatPage::initializeViews, &ChatPage::initializeViews,
view_manager_, view_manager_,
[this](const mtx::responses::Rooms &rooms) { view_manager_->sync(rooms); }); [this](const mtx::responses::Rooms &rooms) { view_manager_->sync(rooms); },
Qt::QueuedConnection);
connect(this, connect(this,
&ChatPage::initializeEmptyViews, &ChatPage::initializeEmptyViews,
view_manager_, view_manager_,
@ -522,8 +523,6 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
void void
ChatPage::loadStateFromCache() ChatPage::loadStateFromCache()
{ {
emit contentLoaded();
nhlog::db()->info("restoring state from cache"); nhlog::db()->info("restoring state from cache");
try { try {
@ -555,6 +554,8 @@ ChatPage::loadStateFromCache()
getProfileInfo(); getProfileInfo();
emit contentLoaded();
// Start receiving events. // Start receiving events.
emit trySyncCb(); emit trySyncCb();
} }

View file

@ -27,12 +27,12 @@ QHash<QString, QString> authorColors_;
template<class T, class Event> template<class T, class Event>
static DescInfo static DescInfo
createDescriptionInfo(const Event &event, const QString &localUser, const QString &room_id) createDescriptionInfo(const Event &event, const QString &localUser, const QString &displayName)
{ {
const auto msg = std::get<T>(event); const auto msg = std::get<T>(event);
const auto sender = QString::fromStdString(msg.sender); const auto sender = QString::fromStdString(msg.sender);
const auto username = cache::displayName(room_id, sender); const auto username = displayName;
const auto ts = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts); const auto ts = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
return DescInfo{QString::fromStdString(msg.event_id), return DescInfo{QString::fromStdString(msg.event_id),
@ -153,7 +153,7 @@ utils::descriptiveTime(const QDateTime &then)
DescInfo DescInfo
utils::getMessageDescription(const TimelineEvent &event, utils::getMessageDescription(const TimelineEvent &event,
const QString &localUser, const QString &localUser,
const QString &room_id) const QString &displayName)
{ {
using Audio = mtx::events::RoomEvent<mtx::events::msg::Audio>; using Audio = mtx::events::RoomEvent<mtx::events::msg::Audio>;
using Emote = mtx::events::RoomEvent<mtx::events::msg::Emote>; using Emote = mtx::events::RoomEvent<mtx::events::msg::Emote>;
@ -168,31 +168,31 @@ utils::getMessageDescription(const TimelineEvent &event,
using Encrypted = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>; using Encrypted = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
if (std::holds_alternative<Audio>(event)) { if (std::holds_alternative<Audio>(event)) {
return createDescriptionInfo<Audio>(event, localUser, room_id); return createDescriptionInfo<Audio>(event, localUser, displayName);
} else if (std::holds_alternative<Emote>(event)) { } else if (std::holds_alternative<Emote>(event)) {
return createDescriptionInfo<Emote>(event, localUser, room_id); return createDescriptionInfo<Emote>(event, localUser, displayName);
} else if (std::holds_alternative<File>(event)) { } else if (std::holds_alternative<File>(event)) {
return createDescriptionInfo<File>(event, localUser, room_id); return createDescriptionInfo<File>(event, localUser, displayName);
} else if (std::holds_alternative<Image>(event)) { } else if (std::holds_alternative<Image>(event)) {
return createDescriptionInfo<Image>(event, localUser, room_id); return createDescriptionInfo<Image>(event, localUser, displayName);
} else if (std::holds_alternative<Notice>(event)) { } else if (std::holds_alternative<Notice>(event)) {
return createDescriptionInfo<Notice>(event, localUser, room_id); return createDescriptionInfo<Notice>(event, localUser, displayName);
} else if (std::holds_alternative<Text>(event)) { } else if (std::holds_alternative<Text>(event)) {
return createDescriptionInfo<Text>(event, localUser, room_id); return createDescriptionInfo<Text>(event, localUser, displayName);
} else if (std::holds_alternative<Video>(event)) { } else if (std::holds_alternative<Video>(event)) {
return createDescriptionInfo<Video>(event, localUser, room_id); return createDescriptionInfo<Video>(event, localUser, displayName);
} else if (std::holds_alternative<CallInvite>(event)) { } else if (std::holds_alternative<CallInvite>(event)) {
return createDescriptionInfo<CallInvite>(event, localUser, room_id); return createDescriptionInfo<CallInvite>(event, localUser, displayName);
} else if (std::holds_alternative<CallAnswer>(event)) { } else if (std::holds_alternative<CallAnswer>(event)) {
return createDescriptionInfo<CallAnswer>(event, localUser, room_id); return createDescriptionInfo<CallAnswer>(event, localUser, displayName);
} else if (std::holds_alternative<CallHangUp>(event)) { } else if (std::holds_alternative<CallHangUp>(event)) {
return createDescriptionInfo<CallHangUp>(event, localUser, room_id); return createDescriptionInfo<CallHangUp>(event, localUser, displayName);
} else if (std::holds_alternative<mtx::events::Sticker>(event)) { } else if (std::holds_alternative<mtx::events::Sticker>(event)) {
return createDescriptionInfo<mtx::events::Sticker>(event, localUser, room_id); return createDescriptionInfo<mtx::events::Sticker>(event, localUser, displayName);
} else if (auto msg = std::get_if<Encrypted>(&event); msg != nullptr) { } else if (auto msg = std::get_if<Encrypted>(&event); msg != nullptr) {
const auto sender = QString::fromStdString(msg->sender); const auto sender = QString::fromStdString(msg->sender);
const auto username = cache::displayName(room_id, sender); const auto username = displayName;
const auto ts = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts); const auto ts = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts);
DescInfo info; DescInfo info;

View file

@ -67,7 +67,9 @@ descriptiveTime(const QDateTime &then);
//! Generate a message description from the event to be displayed //! Generate a message description from the event to be displayed
//! in the RoomList. //! in the RoomList.
DescInfo DescInfo
getMessageDescription(const TimelineEvent &event, const QString &localUser, const QString &room_id); getMessageDescription(const TimelineEvent &event,
const QString &localUser,
const QString &displayName);
//! Get the first character of a string, taking into account that //! Get the first character of a string, taking into account that
//! surrogate pairs might be in use. //! surrogate pairs might be in use.

View file

@ -709,7 +709,10 @@ TimelineModel::updateLastMessage()
continue; continue;
auto description = utils::getMessageDescription( auto description = utils::getMessageDescription(
*event, QString::fromStdString(http::client()->user_id().to_string()), room_id_); *event,
QString::fromStdString(http::client()->user_id().to_string()),
cache::displayName(room_id_,
QString::fromStdString(mtx::accessors::sender(*event))));
emit manager_->updateRoomsLastMessage(room_id_, description); emit manager_->updateRoomsLastMessage(room_id_, description);
return; return;
} }