Skip to main content

xmtp_mls/
lib.rs

1#![recursion_limit = "256"]
2#![warn(clippy::unwrap_used)]
3
4pub mod builder;
5pub mod client;
6pub mod context;
7mod definitions;
8pub mod groups;
9pub mod identity;
10pub mod identity_updates;
11mod intents;
12pub mod messages;
13pub mod mls_store;
14mod mutex_registry;
15pub mod server_configuration;
16mod state_tx;
17pub use client::VisibilityConfirmationOptions;
18pub mod subscriptions;
19pub mod utils;
20pub mod worker;
21pub use definitions::*;
22
23#[cfg(any(test, feature = "test-utils"))]
24pub mod test;
25mod traits;
26
27#[cfg(test)]
28use crate::groups::GroupError;
29pub use client::{Client, Network};
30#[cfg(test)]
31use parking_lot::Mutex;
32#[cfg(test)]
33use std::collections::HashMap;
34#[cfg(test)]
35use std::sync::Arc;
36#[cfg(test)]
37use tokio::sync::Mutex as TokioMutex;
38pub use xmtp_common as common;
39pub use xmtp_db as db;
40#[cfg(test)]
41use xmtp_db::DuplicateItem;
42use xmtp_db::StorageError;
43pub use xmtp_id::InboxOwner;
44pub use xmtp_mls_common as mls_common;
45pub use xmtp_proto::api_client::*;
46#[cfg(test)]
47use xmtp_proto::types::GroupId;
48
49pub fn version() -> &'static str {
50    env!("CARGO_PKG_VERSION")
51}
52
53/// A manager for group-specific semaphores
54#[cfg(test)]
55#[derive(Debug)]
56pub struct GroupCommitLock {
57    // Storage for group-specific semaphores
58    locks: Mutex<HashMap<GroupId, Arc<TokioMutex<()>>>>,
59}
60
61#[cfg(test)]
62impl Default for GroupCommitLock {
63    fn default() -> Self {
64        Self::new()
65    }
66}
67#[cfg(test)]
68impl GroupCommitLock {
69    /// Create a new `GroupCommitLock`
70    pub fn new() -> Self {
71        Self {
72            locks: Mutex::new(HashMap::new()),
73        }
74    }
75
76    /// Get or create a semaphore for a specific group and acquire it, returning a guard
77    pub async fn get_lock_async(&self, group_id: GroupId) -> MlsGroupGuard {
78        let lock = {
79            let mut locks = self.locks.lock();
80            locks
81                .entry(group_id)
82                .or_insert_with(|| Arc::new(TokioMutex::new(())))
83                .clone()
84        };
85
86        MlsGroupGuard {
87            _permit: lock.lock_owned().await,
88        }
89    }
90
91    /// Get or create a semaphore for a specific group and acquire it synchronously
92    pub fn get_lock_sync(&self, group_id: GroupId) -> Result<MlsGroupGuard, GroupError> {
93        let lock = {
94            let mut locks = self.locks.lock();
95            locks
96                .entry(group_id)
97                .or_insert_with(|| Arc::new(TokioMutex::new(())))
98                .clone()
99        };
100
101        // Synchronously acquire the permit
102        let permit = lock
103            .try_lock_owned()
104            .map_err(|_| GroupError::LockUnavailable)?;
105        Ok(MlsGroupGuard { _permit: permit })
106    }
107}
108/// A guard that releases the semaphore when dropped
109#[cfg(test)]
110pub struct MlsGroupGuard {
111    _permit: tokio::sync::OwnedMutexGuard<()>,
112}
113
114#[cfg_attr(not(target_arch = "wasm32"), ctor::ctor(unsafe))]
115#[cfg(all(test, not(target_arch = "wasm32")))]
116fn test_setup() {
117    xmtp_common::logger();
118    let _ = fdlimit::raise_fd_limit();
119}