Skip to content

Commit

Permalink
feat(base): Create EventCacheStoreLock.
Browse files Browse the repository at this point in the history
  • Loading branch information
Hywan committed Nov 5, 2024
1 parent 7c41935 commit dcb18c3
Showing 1 changed file with 73 additions and 2 deletions.
75 changes: 73 additions & 2 deletions crates/matrix-sdk-base/src/event_cache_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@
//! into the event cache for the actual storage. By default this brings an
//! in-memory store.
use std::{str::Utf8Error, sync::Arc};
use std::{fmt, ops::Deref, str::Utf8Error, sync::Arc};

#[cfg(any(test, feature = "testing"))]
#[macro_use]
pub mod integration_tests;
mod memory_store;
mod traits;

use matrix_sdk_common::store_locks::BackingStore;
use matrix_sdk_common::store_locks::{
BackingStore, CrossProcessStoreLock, CrossProcessStoreLockGuard, LockStoreError,
};
pub use matrix_sdk_store_encryption::Error as StoreEncryptionError;

#[cfg(any(test, feature = "testing"))]
Expand All @@ -37,6 +39,75 @@ pub use self::{
traits::{DynEventCacheStore, EventCacheStore, IntoEventCacheStore},
};

/// The high-level public type to represent an `EventCacheStore` lock.
pub struct EventCacheStoreLock {
/// The inner cross process lock that is used to lock the `EventCacheStore`.
cross_process_lock: CrossProcessStoreLock<LockableEventCacheStore>,

/// The store itself.
///
/// That's the only place where the store exists.
store: Arc<DynEventCacheStore>,
}

impl fmt::Debug for EventCacheStoreLock {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_struct("EventCacheStoreLock").finish_non_exhaustive()
}
}

impl EventCacheStoreLock {
/// Create a new lock around the [`EventCacheStore`].
pub fn new<S>(store: S, key: String, holder: String) -> Self
where
S: IntoEventCacheStore,
{
let store = store.into_event_cache_store();

Self {
cross_process_lock: CrossProcessStoreLock::new(
LockableEventCacheStore(store.clone()),
key,
holder,
),
store,
}
}

/// Acquire a spin lock (see [`CrossProcessStoreLock::spin_lock`]).
pub async fn lock(&self) -> Result<EventCacheStoreLockGuard<'_>, LockStoreError> {
let cross_process_lock_guard = self.cross_process_lock.spin_lock(None).await?;

Ok(EventCacheStoreLockGuard { cross_process_lock_guard, store: self.store.deref() })
}
}

/// An RAII implementation of a “scoped lock” of an [`EventCacheStoreLock`].
/// When this structure is dropped (falls out of scope), the lock will be
/// unlocked.
pub struct EventCacheStoreLockGuard<'a> {
/// The cross process lock guard.
#[allow(unused)]
cross_process_lock_guard: CrossProcessStoreLockGuard,

/// A reference to the store.
store: &'a DynEventCacheStore,
}

impl<'a> fmt::Debug for EventCacheStoreLockGuard<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_struct("EventCacheStoreLockGuard").finish_non_exhaustive()
}
}

impl<'a> Deref for EventCacheStoreLockGuard<'a> {
type Target = DynEventCacheStore;

fn deref(&self) -> &Self::Target {
self.store
}
}

/// Event cache store specific error type.
#[derive(Debug, thiserror::Error)]
pub enum EventCacheStoreError {
Expand Down

0 comments on commit dcb18c3

Please sign in to comment.