refactor(indexeddb): use UUID instead of u64 as media content id

Signed-off-by: Michael Goldenberg <m@mgoldenberg.net>
This commit is contained in:
Michael Goldenberg
2025-10-24 12:47:52 -04:00
committed by Damir Jelić
parent 0ac943b4c4
commit 155a7b481b
6 changed files with 37 additions and 35 deletions
+1 -1
View File
@@ -50,6 +50,7 @@ sha2.workspace = true
thiserror.workspace = true
tokio.workspace = true
tracing.workspace = true
uuid = { workspace = true, features = ["js", "serde", "v4"] }
wasm-bindgen.workspace = true
web-sys = { workspace = true, features = ["IdbKeyRange"] }
zeroize.workspace = true
@@ -71,7 +72,6 @@ tracing-subscriber = { workspace = true, features = [
"registry",
"tracing-log",
] }
uuid.workspace = true
wasm-bindgen-test.workspace = true
web-sys = { workspace = true, features = [
"IdbKeyRange",
@@ -18,7 +18,7 @@ use crate::{
types::UnixTime,
},
serializer::{
indexed_type::constants::{INDEXED_KEY_LOWER_U64, INDEXED_KEY_UPPER_U64},
indexed_type::constants::{INDEXED_KEY_LOWER_UUID, INDEXED_KEY_UPPER_UUID},
INDEXED_KEY_UPPER_DURATION_SECONDS,
},
};
@@ -57,17 +57,17 @@ pub const INDEXED_KEY_UPPER_UNIX_TIME: UnixTime =
UnixTime::AfterEpoch(INDEXED_KEY_UPPER_DURATION_SECONDS);
/// The minimum value for an [`IndexedMediaContentId`] - i.e.,
/// [`INDEXED_KEY_LOWER_U64`].
/// [`INDEXED_KEY_LOWER_UUID`].
///
/// This value is useful for constructing a key range over all keys which
/// contain [`IndexedMediaContentId`] values when used in conjunction with
/// [`INDEXED_KEY_UPPER_MEDIA_CONTENT_ID`].
pub const INDEXED_KEY_LOWER_MEDIA_CONTENT_ID: IndexedMediaContentId = INDEXED_KEY_LOWER_U64;
pub const INDEXED_KEY_LOWER_MEDIA_CONTENT_ID: IndexedMediaContentId = INDEXED_KEY_LOWER_UUID;
/// The maximum value for an [`IndexedMediaContentId`] - i.e.,
/// [`INDEXED_KEY_UPPER_U64`].
/// [`INDEXED_KEY_UPPER_UUID`].
///
/// This value is useful for constructing a key range over all keys which
/// contain [`IndexedMediaContentId`] values when used in conjunction with
/// [`INDEXED_KEY_LOWER_MEDIA_CONTENT_ID`].
pub const INDEXED_KEY_UPPER_MEDIA_CONTENT_ID: IndexedMediaContentId = INDEXED_KEY_UPPER_U64;
pub const INDEXED_KEY_UPPER_MEDIA_CONTENT_ID: IndexedMediaContentId = INDEXED_KEY_UPPER_UUID;
@@ -37,6 +37,7 @@ use matrix_sdk_crypto::CryptoStoreError;
use ruma::MxcUri;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;
use crate::{
media_store::{
@@ -82,7 +83,7 @@ pub type IndexedMediaMetadataContent = MaybeEncrypted;
pub type IndexedMediaContentSize = usize;
/// A representation of the identifier [`MediaContent::content_id`]
pub type IndexedMediaContentId = u64;
pub type IndexedMediaContentId = Uuid;
/// A (possibly) encrypted representation of [`MediaContent::data`]
pub type IndexedMediaContentData = Vec<u8>;
@@ -369,7 +370,7 @@ impl IndexedMediaMetadataContentSizeKey {
}
/// Returns the identifier of the associated [`IndexedMediaContent`]
pub fn content_id(&self) -> u64 {
pub fn content_id(&self) -> Uuid {
self.2
}
}
@@ -465,7 +466,7 @@ impl IndexedMediaMetadataLastAccessKey {
}
/// Returns the identifier of the associated [`IndexedMediaContent`]
pub fn content_id(&self) -> u64 {
pub fn content_id(&self) -> Uuid {
self.2
}
}
@@ -562,7 +563,7 @@ impl IndexedMediaMetadataRetentionKey {
}
/// Returns the identifier of the associated [`IndexedMediaContent`]
pub fn content_id(&self) -> u64 {
pub fn content_id(&self) -> Uuid {
self.3
}
}
@@ -709,7 +710,7 @@ impl Indexed for MediaContent {
pub struct IndexedMediaContentIdKey(IndexedMediaContentId);
impl Deref for IndexedMediaContentIdKey {
type Target = u64;
type Target = Uuid;
fn deref(&self) -> &Self::Target {
&self.0
@@ -20,6 +20,7 @@ use matrix_sdk_base::media::{
MediaRequestParameters,
};
use ruma::MxcUri;
use uuid::Uuid;
use crate::{
media_store::{
@@ -192,7 +193,7 @@ impl<'a> IndexeddbMediaStoreTransaction<'a> {
) -> Result<Option<(IndexedMediaMetadata, IndexedMediaContent)>, TransactionError> {
let content_id = match self.get_media_metadata_by_id(&media.request_parameters).await? {
Some(metadata) => metadata.content_id,
None => self.get_next_media_content_id().await?,
None => Uuid::new_v4(),
};
let content = MediaContent { content_id, data: media.content };
let option = if media.ignore_policy.is_yes() {
@@ -604,30 +605,11 @@ impl<'a> IndexeddbMediaStoreTransaction<'a> {
/// is returned.
pub async fn get_media_content_by_id(
&self,
id: u64,
id: Uuid,
) -> Result<Option<MediaContent>, TransactionError> {
self.get_item_by_key_components::<MediaContent, IndexedMediaContentIdKey>(id).await
}
/// Query IndexedDB for the maximum [`IndexedMediaContentIdKey`] associated
/// with a [`MediaContent`]
pub async fn get_max_media_content_key_by_id(
&self,
) -> Result<Option<IndexedMediaContentIdKey>, TransactionError> {
self.get_max_key::<MediaContent, IndexedMediaContentIdKey>(IndexedKeyRange::all(
self.serializer().inner(),
))
.await
}
/// Query IndexedDB for the next available [`MediaContent::id`]
pub async fn get_next_media_content_id(&self) -> Result<u64, TransactionError> {
Ok(match self.get_max_media_content_key_by_id().await? {
Some(key) => key.checked_add(1).ok_or(TransactionError::NumericalOverflow)?,
None => 0,
})
}
/// Adds [`MediaContent`] to IndexedDB. If an item with the same key already
/// exists, it will be rejected. When the item is successfully added, the
/// function returns the intermediary type [`IndexedMediaContent`] in case
@@ -668,7 +650,7 @@ impl<'a> IndexeddbMediaStoreTransaction<'a> {
}
/// Delete [`MediaContent`] that match the given identifier from IndexedDB
pub async fn delete_media_content_by_id(&self, id: u64) -> Result<(), TransactionError> {
pub async fn delete_media_content_by_id(&self, id: Uuid) -> Result<(), TransactionError> {
self.delete_item_by_key::<MediaContent, IndexedMediaContentIdKey>(id).await
}
}
@@ -20,6 +20,7 @@ use std::{
use matrix_sdk_base::media::{store::IgnoreMediaRetentionPolicy, MediaRequestParameters};
use ruma::time::{SystemTime, UNIX_EPOCH};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Representation of a time-based lock on the entire
/// [`IndexeddbMediaStore`](crate::media_store::IndexeddbMediaStore)
@@ -69,7 +70,7 @@ pub struct MediaMetadata {
#[serde(with = "crate::media_store::serializer::foreign::ignore_media_retention_policy")]
pub ignore_policy: IgnoreMediaRetentionPolicy,
/// The identifier of the associated [`MediaContent`]
pub content_id: u64,
pub content_id: Uuid,
/// The size in bytes of the associated [`MediaContent`]
pub content_size: usize,
}
@@ -78,7 +79,7 @@ pub struct MediaMetadata {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MediaContent {
/// The identifier associated with the given [`MediaContent::data`].
pub content_id: u64,
pub content_id: Uuid,
/// The bytes to be stored in IndexedDB
pub data: Vec<u8>,
}
@@ -14,6 +14,8 @@
use std::{sync::LazyLock, time::Duration};
use uuid::Uuid;
/// The first unicode character, and hence the lower bound for IndexedDB keys
/// (or key components) which are represented as strings.
///
@@ -55,6 +57,22 @@ pub const INDEXED_KEY_LOWER_U64: u64 = u64::MIN;
/// [`INDEXED_KEY_LOWER_U64`].
pub const INDEXED_KEY_UPPER_U64: u64 = js_sys::Number::MAX_SAFE_INTEGER as u64;
/// The minimum possible [`Uuid`].
///
/// This value is useful for constructing a key range over all keys which
/// contain [`Uuid`] values when used in conjunction with
/// [`INDEXED_KEY_UPPER_UUID`].
pub const INDEXED_KEY_LOWER_UUID: Uuid = Uuid::from_u128(u128::MIN);
/// The maximum possible [`Uuid`]. Note that this is not limited by
/// [`js_sys::Number::MAX_SAFE_INTEGER`] as the [`Uuid`]s are serialized
/// either as bytes or a string.
///
/// This value is useful for constructing a key range over all keys which
/// contain [`Uuid`] values when used in conjunction with
/// [`INDEXED_KEY_LOWER_UUID`].
pub const INDEXED_KEY_UPPER_UUID: Uuid = Uuid::from_u128(u128::MAX);
/// The minimum possible [`Duration`].
///
/// This value is useful for constructing a key range over all keys which