refactor(sqlite): Save the event type of an event in the SQLite event cache
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
-- For the event decryption to happen in the event cache we need the ability to
|
||||
-- fetch only `m.room.encrypted` events out of the store.
|
||||
--
|
||||
-- To accomplish that, we are emptying the event cache. New events inserted with
|
||||
-- the event type and the session ID of the room key as separate columns.
|
||||
|
||||
DELETE from linked_chunks;
|
||||
DELETE from event_chunks; -- should be done by cascading
|
||||
DELETE from gap_chunks; -- should be done by cascading
|
||||
DELETE from events;
|
||||
|
||||
DROP TABLE events;
|
||||
|
||||
-- Events and their content.
|
||||
CREATE TABLE "events" (
|
||||
-- The room in which the event is located.
|
||||
"room_id" BLOB NOT NULL,
|
||||
|
||||
-- The `OwnedEventId` of this event.
|
||||
"event_id" BLOB NOT NULL,
|
||||
|
||||
-- The event type of this event.
|
||||
"event_type" BLOB NOT NULL,
|
||||
|
||||
-- The ID of the session that was used to encrypt this event, may be null if
|
||||
-- the event wasn't encrypted.
|
||||
"session_id" BLOB NULL,
|
||||
|
||||
-- JSON serialized `TimelineEvent` (encrypted value).
|
||||
"content" BLOB NOT NULL,
|
||||
|
||||
-- If this event is an aggregation (related event), the event id of the event it relates to.
|
||||
-- Can be null if this event isn't an aggregation.
|
||||
"relates_to" BLOB,
|
||||
|
||||
-- If this event is an aggregation (related event), the kind of relation it has to the event it
|
||||
-- relates to.
|
||||
-- Can be null if this event isn't an aggregation.
|
||||
"rel_type" BLOB,
|
||||
|
||||
-- Primary key is the event ID.
|
||||
PRIMARY KEY (event_id)
|
||||
)
|
||||
WITHOUT ROWID;
|
||||
|
||||
-- Add an index to speed up queries that look for related events in a room.
|
||||
CREATE INDEX "relates_to_idx"
|
||||
ON "events" ("room_id", "relates_to");
|
||||
|
||||
-- Add an index to speed up queries that look for related events in a room, with an additional
|
||||
-- filter.
|
||||
CREATE INDEX "relates_to_rel_type_idx"
|
||||
ON "events" ("room_id", "relates_to", "rel_type");
|
||||
|
||||
-- Add an index to speed up queries that look for related events in a room.
|
||||
CREATE INDEX "event_type_index"
|
||||
ON "events" ("room_id", "event_type", "session_id");
|
||||
@@ -53,6 +53,7 @@ use crate::{
|
||||
mod keys {
|
||||
// Tables
|
||||
pub const LINKED_CHUNKS: &str = "linked_chunks";
|
||||
pub const EVENTS: &str = "events";
|
||||
}
|
||||
|
||||
/// The database name.
|
||||
@@ -63,7 +64,7 @@ const DATABASE_NAME: &str = "matrix-sdk-event-cache.sqlite3";
|
||||
/// This is used to figure whether the SQLite database requires a migration.
|
||||
/// Every new SQL migration should imply a bump of this number, and changes in
|
||||
/// the [`run_migrations`] function.
|
||||
const DATABASE_VERSION: u8 = 11;
|
||||
const DATABASE_VERSION: u8 = 12;
|
||||
|
||||
/// The string used to identify a chunk of type events, in the `type` field in
|
||||
/// the database.
|
||||
@@ -472,6 +473,16 @@ async fn run_migrations(conn: &SqliteAsyncConn, version: u8) -> Result<()> {
|
||||
.await?;
|
||||
}
|
||||
|
||||
if version < 12 {
|
||||
conn.with_transaction(|txn| {
|
||||
txn.execute_batch(include_str!(
|
||||
"../migrations/event_cache_store/012_store_event_type.sql"
|
||||
))?;
|
||||
txn.set_db_version(12)
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -632,7 +643,7 @@ impl EventCacheStore for SqliteEventCacheStore {
|
||||
// deduplicated and moved to another position; or because it was inserted
|
||||
// outside the context of a linked chunk (e.g. pinned event).
|
||||
let mut content_statement = txn.prepare(
|
||||
"INSERT OR REPLACE INTO events(room_id, event_id, content, relates_to, rel_type) VALUES (?, ?, ?, ?, ?)"
|
||||
"INSERT OR REPLACE INTO events(room_id, event_id, event_type, session_id, content, relates_to, rel_type) VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
)?;
|
||||
|
||||
let invalid_event = |event: TimelineEvent| {
|
||||
@@ -641,20 +652,28 @@ impl EventCacheStore for SqliteEventCacheStore {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some((event_id.to_string(), event))
|
||||
let Some(event_type) = event.kind.event_type() else {
|
||||
error!(%event_id, "Trying to save an event with no event type");
|
||||
return None;
|
||||
};
|
||||
|
||||
Some((event_id.to_string(), event_type, event))
|
||||
};
|
||||
|
||||
let room_id = linked_chunk_id.room_id();
|
||||
let hashed_room_id = this.encode_key(keys::LINKED_CHUNKS, room_id);
|
||||
|
||||
for (i, (event_id, event)) in items.into_iter().filter_map(invalid_event).enumerate() {
|
||||
for (i, (event_id, event_type, event)) in items.into_iter().filter_map(invalid_event).enumerate() {
|
||||
// Insert the location information into the database.
|
||||
let index = at.index() + i;
|
||||
chunk_statement.execute((chunk_id, &hashed_linked_chunk_id, &event_id, index))?;
|
||||
|
||||
let session_id = event.kind.session_id().map(|s| this.encode_key(keys::EVENTS, s));
|
||||
let event_type = this.encode_key(keys::EVENTS, event_type);
|
||||
|
||||
// Now, insert the event content into the database.
|
||||
let encoded_event = this.encode_event(&event)?;
|
||||
content_statement.execute((&hashed_room_id, event_id, encoded_event.content, encoded_event.relates_to, encoded_event.rel_type))?;
|
||||
content_statement.execute((&hashed_room_id, event_id, event_type, session_id, encoded_event.content, encoded_event.relates_to, encoded_event.rel_type))?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,6 +690,14 @@ impl EventCacheStore for SqliteEventCacheStore {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(event_type) = event.kind.event_type() else {
|
||||
error!(%event_id, "Trying to save an event with no event type");
|
||||
continue;
|
||||
};
|
||||
|
||||
let session_id = event.kind.session_id().map(|s| this.encode_key(keys::EVENTS, s));
|
||||
let event_type = this.encode_key(keys::EVENTS, event_type);
|
||||
|
||||
// Replace the event's content. Really we'd like to update, but in case the
|
||||
// event id changed, we are a bit lenient here and will allow an insertion
|
||||
// of the new event.
|
||||
@@ -678,8 +705,8 @@ impl EventCacheStore for SqliteEventCacheStore {
|
||||
let room_id = linked_chunk_id.room_id();
|
||||
let hashed_room_id = this.encode_key(keys::LINKED_CHUNKS, room_id);
|
||||
txn.execute(
|
||||
"INSERT OR REPLACE INTO events(room_id, event_id, content, relates_to, rel_type) VALUES (?, ?, ?, ?, ?)"
|
||||
, (&hashed_room_id, &event_id, encoded_event.content, encoded_event.relates_to, encoded_event.rel_type))?;
|
||||
"INSERT OR REPLACE INTO events(room_id, event_id, event_type, session_id, content, relates_to, rel_type) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
(&hashed_room_id, &event_id, event_type, session_id, encoded_event.content, encoded_event.relates_to, encoded_event.rel_type))?;
|
||||
|
||||
// Replace the event id in the linked chunk, in case it changed.
|
||||
txn.execute(
|
||||
@@ -1336,6 +1363,14 @@ impl EventCacheStore for SqliteEventCacheStore {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Some(event_type) = event.kind.event_type() else {
|
||||
error!(%event_id, "Trying to save an event with no event type");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let event_type = self.encode_key(keys::EVENTS, event_type);
|
||||
let session_id = event.kind.session_id().map(|s| self.encode_key(keys::EVENTS, s));
|
||||
|
||||
let hashed_room_id = self.encode_key(keys::LINKED_CHUNKS, room_id);
|
||||
let event_id = event_id.to_string();
|
||||
let encoded_event = self.encode_event(&event)?;
|
||||
@@ -1344,8 +1379,8 @@ impl EventCacheStore for SqliteEventCacheStore {
|
||||
.await?
|
||||
.with_transaction(move |txn| -> Result<_> {
|
||||
txn.execute(
|
||||
"INSERT OR REPLACE INTO events(room_id, event_id, content, relates_to, rel_type) VALUES (?, ?, ?, ?, ?)"
|
||||
, (&hashed_room_id, &event_id, encoded_event.content, encoded_event.relates_to, encoded_event.rel_type))?;
|
||||
"INSERT OR REPLACE INTO events(room_id, event_id, event_type, session_id, content, relates_to, rel_type) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
(&hashed_room_id, &event_id, event_type, session_id, encoded_event.content, encoded_event.relates_to, encoded_event.rel_type))?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user