From 6ff8a26ccaf538a05055a984b6a4ece847897ad4 Mon Sep 17 00:00:00 2001 From: Michael Goldenberg Date: Fri, 15 Aug 2025 10:26:53 -0400 Subject: [PATCH] refactor(indexeddb): add room-based index to event object store in preparation for linked chunk id as primary key Signed-off-by: Michael Goldenberg --- .../src/event_cache_store/migrations.rs | 11 +++++ .../src/event_cache_store/serializer/types.rs | 47 ++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs b/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs index 6745feca3..30649559f 100644 --- a/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs +++ b/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs @@ -118,6 +118,8 @@ pub mod v1 { pub const LINKED_CHUNKS_NEXT_KEY_PATH: &str = "next"; pub const EVENTS: &str = "events"; pub const EVENTS_KEY_PATH: &str = "id"; + pub const EVENTS_ROOM: &str = "events_room"; + pub const EVENTS_ROOM_KEY_PATH: &str = "room"; pub const EVENTS_POSITION: &str = "events_position"; pub const EVENTS_POSITION_KEY_PATH: &str = "position"; pub const EVENTS_RELATION: &str = "events_relation"; @@ -169,6 +171,7 @@ pub mod v1 { /// Create an object store for tracking information about events. /// /// * Primary Key - `id` + /// * Index (unique) - `room` - tracks whether an event is in a given room /// * Index (unique) - `position` - tracks position of an event in linked /// chunks /// * Index - `relation` - tracks any event to which the given event is @@ -178,6 +181,14 @@ pub mod v1 { object_store_params.key_path(Some(&keys::EVENTS_KEY_PATH.into())); let events = db.create_object_store_with_params(keys::EVENTS, &object_store_params)?; + let events_room_params = IdbIndexParameters::new(); + events_room_params.set_unique(true); + events.create_index_with_params( + keys::EVENTS_ROOM, + &keys::EVENTS_ROOM_KEY_PATH.into(), + &events_room_params, + ); + let events_position_params = IdbIndexParameters::new(); events_position_params.set_unique(true); events.create_index_with_params( diff --git a/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs b/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs index 2bbd80ab6..abd796cee 100644 --- a/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs +++ b/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs @@ -448,6 +448,9 @@ impl<'a> IndexedPrefixKeyComponentBounds<'a, Chunk, &'a RoomId> for IndexedNextC pub struct IndexedEvent { /// The primary key of the object store. pub id: IndexedEventIdKey, + /// An indexed key on the object store, which represents the room in which + /// the event exists + pub room: IndexedEventRoomKey, /// An indexed key on the object store, which represents the position of the /// event, if it is in a chunk. pub position: Option, @@ -478,6 +481,7 @@ impl Indexed for Event { ) -> Result { let event_id = self.event_id().ok_or(Self::Error::NoEventId)?; let id = IndexedEventIdKey::encode((self.room_id(), &event_id), serializer); + let room = IndexedEventRoomKey::encode((self.room_id(), &event_id), serializer); let position = self.position().map(|position| { IndexedEventPositionKey::encode((self.room_id(), position), serializer) }); @@ -487,7 +491,13 @@ impl Indexed for Event { serializer, ) }); - Ok(IndexedEvent { id, position, relation, content: serializer.maybe_encrypt_value(self)? }) + Ok(IndexedEvent { + id, + room, + position, + relation, + content: serializer.maybe_encrypt_value(self)?, + }) } fn from_indexed( @@ -530,6 +540,41 @@ impl IndexedPrefixKeyBounds for IndexedEventIdKey { pub type IndexedEventId = String; +/// The value associated with the [primary key](IndexedEvent::id) of the +/// [`EVENTS`][1] object store, which is constructed from: +/// +/// - The (possibly) encrypted Room ID +/// - The (possibly) encrypted Event ID. +/// +/// [1]: crate::event_cache_store::migrations::v1::create_events_object_store +#[derive(Debug, Serialize, Deserialize)] +pub struct IndexedEventRoomKey(IndexedRoomId, IndexedEventId); + +impl IndexedKey for IndexedEventRoomKey { + const INDEX: Option<&'static str> = Some(keys::EVENTS_ROOM); + + type KeyComponents<'a> = (&'a RoomId, &'a EventId); + + fn encode( + (room_id, event_id): Self::KeyComponents<'_>, + serializer: &IndexeddbSerializer, + ) -> Self { + let room_id = serializer.encode_key_as_string(keys::ROOMS, room_id.as_str()); + let event_id = serializer.encode_key_as_string(keys::EVENTS, event_id); + Self(room_id, event_id) + } +} + +impl IndexedPrefixKeyBounds for IndexedEventRoomKey { + fn lower_key_with_prefix(room_id: &RoomId, serializer: &IndexeddbSerializer) -> Self { + Self::encode((room_id, &*INDEXED_KEY_LOWER_EVENT_ID), serializer) + } + + fn upper_key_with_prefix(room_id: &RoomId, serializer: &IndexeddbSerializer) -> Self { + Self::encode((room_id, &*INDEXED_KEY_UPPER_EVENT_ID), serializer) + } +} + /// The value associated with the [`position`](IndexedEvent::position) index of /// the [`EVENTS`][1] object store, which is constructed from: ///