Skip to content

Commit 8e66963

Browse files
mgoldenbergHywan
authored andcommitted
refactor(indexeddb): add types and migrations for storing media via event cache
Signed-off-by: Michael Goldenberg <[email protected]>
1 parent aa02e31 commit 8e66963

File tree

4 files changed

+100
-2
lines changed

4 files changed

+100
-2
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/matrix-sdk-indexeddb/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ js-sys.workspace = true
3232
matrix-sdk-base = { workspace = true, features = ["js"], optional = true }
3333
matrix-sdk-crypto = { workspace = true, features = ["js"], optional = true }
3434
matrix-sdk-store-encryption.workspace = true
35+
rmp-serde.workspace = true
3536
ruma.workspace = true
3637
serde.workspace = true
3738
serde-wasm-bindgen = "0.6.5"

crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ pub mod v1 {
131131
pub const GAPS: &str = "gaps";
132132
pub const GAPS_KEY_PATH: &str = "id";
133133
pub const MEDIA_RETENTION_POLICY_KEY: &str = "media_retention_policy";
134+
pub const MEDIA: &str = "media";
135+
pub const MEDIA_KEY_PATH: &str = "id";
134136
}
135137

136138
/// Create all object stores and indices for v1 database
@@ -140,6 +142,7 @@ pub mod v1 {
140142
create_linked_chunks_object_store(db)?;
141143
create_events_object_store(db)?;
142144
create_gaps_object_store(db)?;
145+
create_media_object_store(db)?;
143146
Ok(())
144147
}
145148

@@ -218,4 +221,14 @@ pub mod v1 {
218221
let _ = db.create_object_store_with_params(keys::GAPS, &object_store_params)?;
219222
Ok(())
220223
}
224+
225+
/// Create an object store for tracking information about media.
226+
///
227+
/// * Primary Key - `id`
228+
fn create_media_object_store(db: &IdbDatabase) -> Result<(), DomException> {
229+
let mut object_store_params = IdbObjectStoreParameters::new();
230+
object_store_params.key_path(Some(&keys::MEDIA_KEY_PATH.into()));
231+
let _ = db.create_object_store_with_params(keys::MEDIA, &object_store_params)?;
232+
Ok(())
233+
}
221234
}

crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
use std::sync::LazyLock;
3131

3232
use matrix_sdk_base::{
33-
event_cache::store::media::MediaRetentionPolicy,
33+
event_cache::store::media::{IgnoreMediaRetentionPolicy, MediaRetentionPolicy},
3434
linked_chunk::{ChunkIdentifier, LinkedChunkId},
35+
media::{MediaRequestParameters, UniqueKey},
3536
};
3637
use matrix_sdk_crypto::CryptoStoreError;
3738
use ruma::{events::relation::RelationType, EventId, OwnedEventId, RoomId};
@@ -45,7 +46,7 @@ use crate::{
4546
Indexed, IndexedKey, IndexedKeyBounds, IndexedKeyComponentBounds,
4647
IndexedPrefixKeyBounds, IndexedPrefixKeyComponentBounds,
4748
},
48-
types::{Chunk, Event, Gap, Lease, Position},
49+
types::{Chunk, Event, Gap, Lease, Media, Position},
4950
},
5051
serializer::{IndexeddbSerializer, MaybeEncrypted},
5152
};
@@ -281,6 +282,14 @@ pub type IndexedGapContent = MaybeEncrypted;
281282
/// A (possibly) encrypted representation of a [`MediaRetentionPolicy`]
282283
pub type IndexedMediaRetentionPolicyContent = MaybeEncrypted;
283284

285+
/// A (possibly) encrypted representation of a [`MediaMetadata`][1]
286+
///
287+
/// [1]: crate::event_cache_store::types::MediaMetadata
288+
pub type IndexedMediaMetadata = MaybeEncrypted;
289+
290+
/// A (possibly) encrypted representation of [`Media::content`]
291+
pub type IndexedMediaContent = Vec<u8>;
292+
284293
/// Represents the [`LEASES`][1] object store.
285294
///
286295
/// [1]: crate::event_cache_store::migrations::v1::create_lease_object_store
@@ -883,3 +892,77 @@ impl IndexedKey<MediaRetentionPolicy> for IndexedCoreIdKey {
883892
serializer.encode_key_as_string(keys::CORE, keys::MEDIA_RETENTION_POLICY_KEY)
884893
}
885894
}
895+
896+
/// Represents the [`MEDIA`][1] object store.
897+
///
898+
/// [1]: crate::event_cache_store::migrations::v1::create_media_object_store
899+
#[derive(Debug, Serialize, Deserialize)]
900+
pub struct IndexedMedia {
901+
/// The primary key of the object store
902+
pub id: IndexedMediaIdKey,
903+
/// The (possibly) encrypted metadata - i.e., [`MediaMetadata`][1]
904+
///
905+
/// [1]: crate::event_cache_store::types::MediaMetadata
906+
pub metadata: IndexedMediaMetadata,
907+
/// The (possibly) encrypted content - i.e., [`Media::content`]
908+
pub content: IndexedMediaContent,
909+
}
910+
911+
#[derive(Debug, Error)]
912+
pub enum IndexedMediaError {
913+
#[error("crypto store: {0}")]
914+
CryptoStore(#[from] CryptoStoreError),
915+
#[error("serialization: {0}")]
916+
Serialization(#[from] rmp_serde::encode::Error),
917+
#[error("deserialization: {0}")]
918+
Deserialization(#[from] rmp_serde::decode::Error),
919+
}
920+
921+
impl Indexed for Media {
922+
const OBJECT_STORE: &'static str = keys::MEDIA;
923+
924+
type IndexedType = IndexedMedia;
925+
type Error = IndexedMediaError;
926+
927+
fn to_indexed(
928+
&self,
929+
serializer: &IndexeddbSerializer,
930+
) -> Result<Self::IndexedType, Self::Error> {
931+
let content = rmp_serde::to_vec_named(&serializer.maybe_encrypt_value(&self.content)?)?;
932+
Ok(Self::IndexedType {
933+
id: <IndexedMediaIdKey as IndexedKey<Self>>::encode(
934+
&self.metadata.request_parameters,
935+
serializer,
936+
),
937+
metadata: serializer.maybe_encrypt_value(&self.metadata)?,
938+
content,
939+
})
940+
}
941+
942+
fn from_indexed(
943+
indexed: Self::IndexedType,
944+
serializer: &IndexeddbSerializer,
945+
) -> Result<Self, Self::Error> {
946+
Ok(Self {
947+
metadata: serializer.maybe_decrypt_value(indexed.metadata)?,
948+
content: serializer.maybe_decrypt_value(rmp_serde::from_slice(&indexed.content)?)?,
949+
})
950+
}
951+
}
952+
953+
/// The primary key of the [`MEDIA`][1] object store, which is constructed from:
954+
///
955+
/// - The (possibly) hashed value returned by
956+
/// [`MediaRequestParameters::unique_key`]
957+
///
958+
/// [1]: crate::event_cache_store::migrations::v1::create_media_object_store
959+
#[derive(Debug, Serialize, Deserialize)]
960+
pub struct IndexedMediaIdKey(String);
961+
962+
impl IndexedKey<Media> for IndexedMediaIdKey {
963+
type KeyComponents<'a> = &'a MediaRequestParameters;
964+
965+
fn encode(components: Self::KeyComponents<'_>, serializer: &IndexeddbSerializer) -> Self {
966+
Self(serializer.encode_key_as_string(keys::MEDIA, components.unique_key()))
967+
}
968+
}

0 commit comments

Comments
 (0)