Skip to content

Commit cea5c19

Browse files
mgoldenbergHywan
authored andcommitted
refactor(indexeddb): add migrations and types for media last access index
Signed-off-by: Michael Goldenberg <[email protected]>
1 parent ad4cb4f commit cea5c19

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ pub mod v1 {
137137
pub const MEDIA_SOURCE_KEY_PATH: &str = "source";
138138
pub const MEDIA_CONTENT_SIZE: &str = "media_content_size";
139139
pub const MEDIA_CONTENT_SIZE_KEY_PATH: &str = "content_size";
140+
pub const MEDIA_LAST_ACCESS: &str = "media_last_access";
141+
pub const MEDIA_LAST_ACCESS_KEY_PATH: &str = "last_access";
140142
}
141143

142144
/// Create all object stores and indices for v1 database
@@ -233,6 +235,8 @@ pub mod v1 {
233235
/// media
234236
/// * Index - `content_size` - tracks the size of the media content and
235237
/// whether to ignore the [`MediaRetentionPolicy`][2]
238+
/// * Index - `last_access` - tracks the last time the associated media was
239+
/// accessed
236240
///
237241
/// [1]: ruma::events::room::MediaSource
238242
/// [2]: matrix_sdk_base::event_cache::store::media::MediaRetentionPolicy
@@ -242,6 +246,7 @@ pub mod v1 {
242246
let media = db.create_object_store_with_params(keys::MEDIA, &object_store_params)?;
243247
media.create_index(keys::MEDIA_SOURCE, &keys::MEDIA_SOURCE_KEY_PATH.into())?;
244248
media.create_index(keys::MEDIA_CONTENT_SIZE, &keys::MEDIA_CONTENT_SIZE_KEY_PATH.into())?;
249+
media.create_index(keys::MEDIA_LAST_ACCESS, &keys::MEDIA_LAST_ACCESS_KEY_PATH.into())?;
245250
Ok(())
246251
}
247252
}

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

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
//! These types mimic the structure of the object stores and indices created in
2828
//! [`crate::event_cache_store::migrations`].
2929
30-
use std::sync::LazyLock;
30+
use std::{sync::LazyLock, time::Duration};
3131

3232
use matrix_sdk_base::{
3333
event_cache::store::media::{IgnoreMediaRetentionPolicy, MediaRetentionPolicy},
@@ -154,6 +154,22 @@ static INDEXED_KEY_UPPER_EVENT_POSITION: LazyLock<Position> = LazyLock::new(|| P
154154
index: INDEXED_KEY_UPPER_EVENT_INDEX,
155155
});
156156

157+
/// The minimum possible [`Duration`].
158+
///
159+
/// This value is useful for constructing a key range over all keys which
160+
/// contain time-related values when used in conjunction with
161+
/// [`INDEXED_KEY_UPPER_DURATION`].
162+
const INDEXED_KEY_LOWER_DURATION: Duration = Duration::ZERO;
163+
164+
/// A [`Duration`] constructed with [`js_sys::Number::MAX_SAFE_INTEGER`]
165+
/// seconds.
166+
///
167+
/// This value is useful for constructing a key range over all keys which
168+
/// contain time-related values in seconds when used in conjunction with
169+
/// [`INDEXED_KEY_LOWER_DURATION`].
170+
const INDEXED_KEY_UPPER_DURATION_SECONDS: Duration =
171+
Duration::from_secs(js_sys::Number::MAX_SAFE_INTEGER as u64);
172+
157173
/// Representation of a range of keys of type `K`. This is loosely
158174
/// correlated with [IDBKeyRange][1], with a few differences.
159175
///
@@ -300,6 +316,10 @@ pub type IndexedMediaContent = Vec<u8>;
300316
/// is suitable for use in an IndexedDB key
301317
pub type IndexedMediaContentSize = usize;
302318

319+
/// A representation of time in seconds since the [Unix
320+
/// Epoch](std::time::UNIX_EPOCH) which is suitable for use in an IndexedDB key
321+
pub type IndexedSecondsSinceUnixEpoch = u64;
322+
303323
/// Represents the [`LEASES`][1] object store.
304324
///
305325
/// [1]: crate::event_cache_store::migrations::v1::create_lease_object_store
@@ -916,6 +936,9 @@ pub struct IndexedMedia {
916936
/// The size (in bytes) of the media content and whether to ignore the
917937
/// [`MediaRetentionPolicy`]
918938
pub content_size: IndexedMediaContentSizeKey,
939+
/// The last time the media was accessed and whether to ignore the
940+
/// [`MediaRetentionPolicy`]
941+
pub last_access: IndexedMediaLastAccessKey,
919942
/// The (possibly) encrypted metadata - i.e., [`MediaMetadata`][1]
920943
///
921944
/// [1]: crate::event_cache_store::types::MediaMetadata
@@ -958,6 +981,10 @@ impl Indexed for Media {
958981
(self.metadata.ignore_policy, content.len()),
959982
serializer,
960983
),
984+
last_access: IndexedMediaLastAccessKey::encode(
985+
(self.metadata.ignore_policy, self.metadata.last_access),
986+
serializer,
987+
),
961988
metadata: serializer.maybe_encrypt_value(&self.metadata)?,
962989
content,
963990
})
@@ -1070,3 +1097,54 @@ impl<'a> IndexedPrefixKeyComponentBounds<'a, Media, IgnoreMediaRetentionPolicy>
10701097
(prefix, IndexedMediaContentSize::MAX)
10711098
}
10721099
}
1100+
1101+
/// The value associated with the [`last_access`](IndexedMedia::last_access)
1102+
/// index of the [`MEDIA`][1] object store, which is constructed from:
1103+
///
1104+
/// - The value of [`IgnoreMediaRetentionPolicy`]
1105+
/// - The last time the associated [`IndexedMedia`] was accessed (in seconds
1106+
/// since the Unix Epoch)
1107+
///
1108+
/// [1]: crate::event_cache_store::migrations::v1::create_media_object_store
1109+
#[derive(Debug, Serialize, Deserialize)]
1110+
pub struct IndexedMediaLastAccessKey(
1111+
#[serde(with = "ignore_media_retention_policy")] IgnoreMediaRetentionPolicy,
1112+
IndexedSecondsSinceUnixEpoch,
1113+
);
1114+
1115+
impl IndexedKey<Media> for IndexedMediaLastAccessKey {
1116+
type KeyComponents<'a> = (IgnoreMediaRetentionPolicy, Duration);
1117+
1118+
fn encode(
1119+
(ignore_policy, last_access): Self::KeyComponents<'_>,
1120+
_: &IndexeddbSerializer,
1121+
) -> Self {
1122+
Self(ignore_policy, last_access.as_secs())
1123+
}
1124+
}
1125+
1126+
impl IndexedKeyComponentBounds<Media> for IndexedMediaLastAccessKey {
1127+
fn lower_key_components() -> Self::KeyComponents<'static> {
1128+
Self::lower_key_components_with_prefix(IgnoreMediaRetentionPolicy::No)
1129+
}
1130+
1131+
fn upper_key_components() -> Self::KeyComponents<'static> {
1132+
Self::lower_key_components_with_prefix(IgnoreMediaRetentionPolicy::Yes)
1133+
}
1134+
}
1135+
1136+
impl<'a> IndexedPrefixKeyComponentBounds<'a, Media, IgnoreMediaRetentionPolicy>
1137+
for IndexedMediaLastAccessKey
1138+
{
1139+
fn lower_key_components_with_prefix(
1140+
prefix: IgnoreMediaRetentionPolicy,
1141+
) -> Self::KeyComponents<'a> {
1142+
(prefix, INDEXED_KEY_LOWER_DURATION)
1143+
}
1144+
1145+
fn upper_key_components_with_prefix(
1146+
prefix: IgnoreMediaRetentionPolicy,
1147+
) -> Self::KeyComponents<'a> {
1148+
(prefix, INDEXED_KEY_UPPER_DURATION_SECONDS)
1149+
}
1150+
}

0 commit comments

Comments
 (0)