Change cache format to not allow duplicate receipts

Convert list of receipts to map<userId, timestamp>
This commit is contained in:
Konstantinos Sideris 2018-01-14 23:33:12 +02:00
parent fa8061c34b
commit 020a842aef
4 changed files with 15 additions and 33 deletions

View file

@ -44,26 +44,6 @@ from_json(const json &j, ReadReceiptKey &key)
key.room_id = j.at("room_id").get<std::string>(); key.room_id = j.at("room_id").get<std::string>();
} }
//! Decribes a read receipt stored in cache.
struct ReadReceiptValue
{
std::string user_id;
uint64_t ts;
};
inline void
to_json(json &j, const ReadReceiptValue &value)
{
j = json{{"user_id", value.user_id}, {"ts", value.ts}};
}
inline void
from_json(const json &j, ReadReceiptValue &value)
{
value.user_id = j.at("user_id").get<std::string>();
value.ts = j.at("ts").get<uint64_t>();
}
class Cache class Cache
{ {
public: public:
@ -100,7 +80,7 @@ public:
//! Retrieve all the read receipts for the given event id and room. //! Retrieve all the read receipts for the given event id and room.
//! //!
//! Returns a map of user ids and the time of the read receipt in milliseconds. //! Returns a map of user ids and the time of the read receipt in milliseconds.
using UserReceipts = std::multimap<uint64_t, std::string>; using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
UserReceipts readReceipts(const QString &event_id, const QString &room_id); UserReceipts readReceipts(const QString &event_id, const QString &room_id);
QByteArray image(const QString &url) const; QByteArray image(const QString &url) const;

View file

@ -37,7 +37,7 @@ public:
explicit ReadReceipts(QWidget *parent = nullptr); explicit ReadReceipts(QWidget *parent = nullptr);
public slots: public slots:
void addUsers(const std::multimap<uint64_t, std::string> &users); void addUsers(const std::multimap<uint64_t, std::string, std::greater<uint64_t>> &users);
protected: protected:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;

View file

@ -25,11 +25,14 @@
#include "Cache.h" #include "Cache.h"
#include "RoomState.h" #include "RoomState.h"
static const std::string CURRENT_CACHE_FORMAT_VERSION("2017.12.10"); static const std::string CURRENT_CACHE_FORMAT_VERSION("2018.01.14");
static const lmdb::val NEXT_BATCH_KEY("next_batch"); static const lmdb::val NEXT_BATCH_KEY("next_batch");
static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version"); static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version");
using CachedReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
Cache::Cache(const QString &userId) Cache::Cache(const QString &userId)
: env_{nullptr} : env_{nullptr}
, stateDb_{0} , stateDb_{0}
@ -455,10 +458,10 @@ Cache::setInvites(const std::map<std::string, mtx::responses::InvitedRoom> &invi
} }
} }
std::multimap<uint64_t, std::string> CachedReceipts
Cache::readReceipts(const QString &event_id, const QString &room_id) Cache::readReceipts(const QString &event_id, const QString &room_id)
{ {
std::multimap<uint64_t, std::string> receipts; CachedReceipts receipts;
ReadReceiptKey receipt_key{event_id.toStdString(), room_id.toStdString()}; ReadReceiptKey receipt_key{event_id.toStdString(), room_id.toStdString()};
nlohmann::json json_key = receipt_key; nlohmann::json json_key = receipt_key;
@ -476,10 +479,11 @@ Cache::readReceipts(const QString &event_id, const QString &room_id)
if (res) { if (res) {
auto json_response = json::parse(std::string(value.data(), value.size())); auto json_response = json::parse(std::string(value.data(), value.size()));
auto values = json_response.get<std::vector<ReadReceiptValue>>(); auto values = json_response.get<std::map<std::string, uint64_t>>();
for (auto v : values) for (auto v : values)
receipts.emplace(v.ts, v.user_id); // timestamp, user_id
receipts.emplace(v.second, v.first);
} }
} catch (const lmdb::error &e) { } catch (const lmdb::error &e) {
@ -489,7 +493,6 @@ Cache::readReceipts(const QString &event_id, const QString &room_id)
return receipts; return receipts;
} }
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
void void
Cache::updateReadReceipt(const std::string &room_id, const Receipts &receipts) Cache::updateReadReceipt(const std::string &room_id, const Receipts &receipts)
{ {
@ -511,7 +514,7 @@ Cache::updateReadReceipt(const std::string &room_id, const Receipts &receipts)
read_txn.commit(); read_txn.commit();
std::vector<ReadReceiptValue> saved_receipts; std::map<std::string, uint64_t> saved_receipts;
// If an entry for the event id already exists, we would // If an entry for the event id already exists, we would
// merge the existing receipts with the new ones. // merge the existing receipts with the new ones.
@ -520,13 +523,12 @@ Cache::updateReadReceipt(const std::string &room_id, const Receipts &receipts)
json::parse(std::string(prev_value.data(), prev_value.size())); json::parse(std::string(prev_value.data(), prev_value.size()));
// Retrieve the saved receipts. // Retrieve the saved receipts.
saved_receipts = json_value.get<std::vector<ReadReceiptValue>>(); saved_receipts = json_value.get<std::map<std::string, uint64_t>>();
} }
// Append the new ones. // Append the new ones.
for (auto event_receipt : event_receipts) for (auto event_receipt : event_receipts)
saved_receipts.push_back( saved_receipts.emplace(event_receipt.first, event_receipt.second);
ReadReceiptValue{event_receipt.first, event_receipt.second});
// Save back the merged (or only the new) receipts. // Save back the merged (or only the new) receipts.
nlohmann::json json_updated_value = saved_receipts; nlohmann::json json_updated_value = saved_receipts;

View file

@ -96,7 +96,7 @@ ReadReceipts::ReadReceipts(QWidget *parent)
} }
void void
ReadReceipts::addUsers(const std::multimap<uint64_t, std::string> &receipts) ReadReceipts::addUsers(const std::multimap<uint64_t, std::string, std::greater<uint64_t>> &receipts)
{ {
// We want to remove any previous items that have been set. // We want to remove any previous items that have been set.
userList_->clear(); userList_->clear();