Skip to main content

matrix_sdk_base/store/
traits.rs

1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{
16    borrow::Borrow,
17    collections::{BTreeMap, BTreeSet, HashMap},
18    fmt,
19    ops::Deref,
20    sync::Arc,
21};
22
23use as_variant::as_variant;
24use async_trait::async_trait;
25use growable_bloom_filter::GrowableBloom;
26use matrix_sdk_common::{AsyncTraitDeps, ttl::TtlValue};
27use ruma::{
28    EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedMxcUri, OwnedRoomId,
29    OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UserId,
30    api::{
31        MatrixVersion, SupportedVersions,
32        client::{
33            discovery::{
34                discover_homeserver::{self, HomeserverInfo, IdentityServerInfo, TileServerInfo},
35                get_capabilities::v3::Capabilities,
36            },
37            rtc::RtcTransport,
38        },
39    },
40    events::{
41        AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, EmptyStateKey, GlobalAccountDataEvent,
42        GlobalAccountDataEventContent, GlobalAccountDataEventType, RedactContent,
43        RedactedStateEventContent, RoomAccountDataEvent, RoomAccountDataEventContent,
44        RoomAccountDataEventType, StateEventType, StaticEventContent, StaticStateEventContent,
45        presence::PresenceEvent,
46        receipt::{Receipt, ReceiptThread, ReceiptType},
47    },
48    profile::UserProfile,
49    serde::Raw,
50};
51use serde::{Deserialize, Serialize};
52use thiserror::Error;
53use tokio::sync::{Mutex, MutexGuard};
54
55use super::{
56    ChildTransactionId, DependentQueuedRequest, DependentQueuedRequestKind, QueueWedgeError,
57    QueuedRequest, QueuedRequestKind, RoomLoadSettings, StateChanges, StoreError,
58    send_queue::SentRequestKey,
59};
60use crate::{
61    MinimalRoomMemberEvent, RoomInfo, RoomMemberships,
62    deserialized_responses::{
63        DisplayName, RawAnySyncOrStrippedState, RawMemberEvent, RawSyncOrStrippedState,
64    },
65    store::StoredThreadSubscription,
66};
67
68/// An abstract state store trait that can be used to implement different stores
69/// for the SDK.
70#[cfg_attr(target_family = "wasm", async_trait(?Send))]
71#[cfg_attr(not(target_family = "wasm"), async_trait)]
72pub trait StateStore: AsyncTraitDeps {
73    /// The error type used by this state store.
74    type Error: fmt::Debug + Into<StoreError> + From<serde_json::Error>;
75
76    /// Get key-value data from the store.
77    ///
78    /// # Arguments
79    ///
80    /// * `key` - The key to fetch data for.
81    async fn get_kv_data(
82        &self,
83        key: StateStoreDataKey<'_>,
84    ) -> Result<Option<StateStoreDataValue>, Self::Error>;
85
86    /// Put key-value data into the store.
87    ///
88    /// # Arguments
89    ///
90    /// * `key` - The key to identify the data in the store.
91    ///
92    /// * `value` - The data to insert.
93    ///
94    /// Panics if the key and value variants do not match.
95    async fn set_kv_data(
96        &self,
97        key: StateStoreDataKey<'_>,
98        value: StateStoreDataValue,
99    ) -> Result<(), Self::Error>;
100
101    /// Remove key-value data from the store.
102    ///
103    /// # Arguments
104    ///
105    /// * `key` - The key to remove the data for.
106    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error>;
107
108    /// Save the set of state changes in the store.
109    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error>;
110
111    /// Get the stored presence event for the given user.
112    ///
113    /// # Arguments
114    ///
115    /// - `user_id` - The id of the user for which we wish to fetch the presence
116    /// event for.
117    async fn get_presence_event(
118        &self,
119        user_id: &UserId,
120    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error>;
121
122    /// Get the stored presence events for the given users.
123    ///
124    /// # Arguments
125    ///
126    /// * `user_ids` - The IDs of the users to fetch the presence events for.
127    async fn get_presence_events(
128        &self,
129        user_ids: &[OwnedUserId],
130    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error>;
131
132    /// Get a state event out of the state store.
133    ///
134    /// # Arguments
135    ///
136    /// * `room_id` - The id of the room the state event was received for.
137    ///
138    /// * `event_type` - The event type of the state event.
139    async fn get_state_event(
140        &self,
141        room_id: &RoomId,
142        event_type: StateEventType,
143        state_key: &str,
144    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error>;
145
146    /// Get a list of state events for a given room and `StateEventType`.
147    ///
148    /// # Arguments
149    ///
150    /// * `room_id` - The id of the room to find events for.
151    ///
152    /// * `event_type` - The event type.
153    async fn get_state_events(
154        &self,
155        room_id: &RoomId,
156        event_type: StateEventType,
157    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
158
159    /// Get a list of state events for a given room, `StateEventType`, and the
160    /// given state keys.
161    ///
162    /// # Arguments
163    ///
164    /// - `room_id` - The id of the room to find events for.
165    /// - `event_type` - The event type.
166    /// - `state_keys` - The list of state keys to find.
167    async fn get_state_events_for_keys(
168        &self,
169        room_id: &RoomId,
170        event_type: StateEventType,
171        state_keys: &[&str],
172    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
173
174    /// Get the current profile for the given user in the given room.
175    ///
176    /// # Arguments
177    ///
178    /// * `room_id` - The room id the profile is used in.
179    ///
180    /// * `user_id` - The id of the user the profile belongs to.
181    async fn get_profile(
182        &self,
183        room_id: &RoomId,
184        user_id: &UserId,
185    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error>;
186
187    /// Get the current profiles for the given users in the given room.
188    ///
189    /// # Arguments
190    ///
191    /// * `room_id` - The ID of the room the profiles are used in.
192    ///
193    /// * `user_ids` - The IDs of the users the profiles belong to.
194    async fn get_profiles<'a>(
195        &self,
196        room_id: &RoomId,
197        user_ids: &'a [OwnedUserId],
198    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error>;
199
200    /// Get the user ids of members for a given room with the given memberships,
201    /// for stripped and regular rooms alike.
202    async fn get_user_ids(
203        &self,
204        room_id: &RoomId,
205        memberships: RoomMemberships,
206    ) -> Result<Vec<OwnedUserId>, Self::Error>;
207
208    /// Get a set of pure `RoomInfo`s the store knows about.
209    async fn get_room_infos(
210        &self,
211        room_load_settings: &RoomLoadSettings,
212    ) -> Result<Vec<RoomInfo>, Self::Error>;
213
214    /// Get all the users that use the given display name in the given room.
215    ///
216    /// # Arguments
217    ///
218    /// - `room_id` - The id of the room for which the display name users should
219    /// be fetched for.
220    /// - `display_name` - The display name that the users use.
221    async fn get_users_with_display_name(
222        &self,
223        room_id: &RoomId,
224        display_name: &DisplayName,
225    ) -> Result<BTreeSet<OwnedUserId>, Self::Error>;
226
227    /// Get all the users that use the given display names in the given room.
228    ///
229    /// # Arguments
230    ///
231    /// * `room_id` - The ID of the room to fetch the display names for.
232    ///
233    /// * `display_names` - The display names that the users use.
234    async fn get_users_with_display_names<'a>(
235        &self,
236        room_id: &RoomId,
237        display_names: &'a [DisplayName],
238    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error>;
239
240    /// Get an event out of the account data store.
241    ///
242    /// # Arguments
243    ///
244    /// * `event_type` - The event type of the account data event.
245    async fn get_account_data_event(
246        &self,
247        event_type: GlobalAccountDataEventType,
248    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error>;
249
250    /// Get an event out of the room account data store.
251    ///
252    /// # Arguments
253    ///
254    /// - `room_id` - The id of the room for which the room account data event
255    ///   should
256    /// be fetched.
257    /// - `event_type` - The event type of the room account data event.
258    async fn get_room_account_data_event(
259        &self,
260        room_id: &RoomId,
261        event_type: RoomAccountDataEventType,
262    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error>;
263
264    /// Get a user's read receipt for a given room and receipt type and thread.
265    ///
266    /// # Arguments
267    ///
268    /// - `room_id` - The id of the room for which the receipt should be
269    ///   fetched.
270    ///
271    /// - `receipt_type` - The type of the receipt.
272    /// - `receipt_thread` - The thread a receipt applies to.
273    /// - `user_id` - The id of the user for whom the receipt should be fetched.
274    async fn get_user_room_receipt_event(
275        &self,
276        room_id: &RoomId,
277        receipt_type: ReceiptType,
278        receipt_thread: &ReceiptThread,
279        user_id: &UserId,
280    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error>;
281
282    /// Get an event's read receipts for a given room, receipt type, and thread.
283    ///
284    /// # Arguments
285    ///
286    /// - `room_id` - The id of the room for which the receipts should be
287    ///   fetched.
288    ///
289    /// - `receipt_type` - The type of the receipts.
290    /// - `receipt_thread` - The thread a receipt applies to.
291    /// - `event_id` - The id of the event for which the receipts should be
292    ///   fetched.
293    async fn get_event_room_receipt_events(
294        &self,
295        room_id: &RoomId,
296        receipt_type: ReceiptType,
297        receipt_thread: &ReceiptThread,
298        event_id: &EventId,
299    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error>;
300
301    /// Get arbitrary data from the custom store
302    ///
303    /// # Arguments
304    ///
305    /// * `key` - The key to fetch data for
306    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
307
308    /// Put arbitrary data into the custom store, return the data previously
309    /// stored
310    ///
311    /// # Arguments
312    ///
313    /// - `key` - The key to insert data into
314    /// - `value` - The value to insert
315    async fn set_custom_value(
316        &self,
317        key: &[u8],
318        value: Vec<u8>,
319    ) -> Result<Option<Vec<u8>>, Self::Error>;
320
321    /// Put arbitrary data into the custom store, do not attempt to read any
322    /// previous data
323    ///
324    /// Optimization option for set_custom_values for stores that would perform
325    /// better withouts the extra read and the caller not needing that data
326    /// returned. Otherwise this just wraps around `set_custom_data` and
327    /// discards the result.
328    ///
329    /// # Arguments
330    ///
331    /// - `key` - The key to insert data into
332    /// - `value` - The value to insert
333    async fn set_custom_value_no_read(
334        &self,
335        key: &[u8],
336        value: Vec<u8>,
337    ) -> Result<(), Self::Error> {
338        self.set_custom_value(key, value).await.map(|_| ())
339    }
340
341    /// Remove arbitrary data from the custom store and return it if existed
342    ///
343    /// # Arguments
344    ///
345    /// * `key` - The key to remove data from
346    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
347
348    /// Remove a room and all elements associated from the state store.
349    ///
350    /// # Arguments
351    ///
352    /// * `room_id` - The `RoomId` of the room to delete.
353    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error>;
354
355    /// Save a request to be sent by a send queue later (e.g. sending an event).
356    ///
357    /// # Arguments
358    ///
359    /// - `room_id` - The `RoomId` of the send queue's room.
360    /// - `transaction_id` - The unique key identifying the event to be sent
361    ///   (and its transaction). Note: this is expected to be randomly generated
362    ///   and thus unique.
363    /// - `content` - Serializable event content to be sent.
364    async fn save_send_queue_request(
365        &self,
366        room_id: &RoomId,
367        transaction_id: OwnedTransactionId,
368        created_at: MilliSecondsSinceUnixEpoch,
369        request: QueuedRequestKind,
370        priority: usize,
371    ) -> Result<(), Self::Error>;
372
373    /// Updates a send queue request with the given content, and resets its
374    /// error status.
375    ///
376    /// # Arguments
377    ///
378    /// - `room_id` - The `RoomId` of the send queue's room.
379    /// - `transaction_id` - The unique key identifying the request to be sent
380    ///   (and its transaction).
381    /// - `content` - Serializable event content to replace the original one.
382    ///
383    /// Returns true if a request has been updated, or false otherwise.
384    async fn update_send_queue_request(
385        &self,
386        room_id: &RoomId,
387        transaction_id: &TransactionId,
388        content: QueuedRequestKind,
389    ) -> Result<bool, Self::Error>;
390
391    /// Remove a request previously inserted with
392    /// [`Self::save_send_queue_request`] from the database, based on its
393    /// transaction id.
394    ///
395    /// Returns true if something has been removed, or false otherwise.
396    async fn remove_send_queue_request(
397        &self,
398        room_id: &RoomId,
399        transaction_id: &TransactionId,
400    ) -> Result<bool, Self::Error>;
401
402    /// Loads all the send queue requests for the given room.
403    ///
404    /// The resulting vector of queued requests should be ordered from higher
405    /// priority to lower priority, and respect the insertion order when
406    /// priorities are equal.
407    async fn load_send_queue_requests(
408        &self,
409        room_id: &RoomId,
410    ) -> Result<Vec<QueuedRequest>, Self::Error>;
411
412    /// Updates the send queue error status (wedge) for a given send queue
413    /// request.
414    async fn update_send_queue_request_status(
415        &self,
416        room_id: &RoomId,
417        transaction_id: &TransactionId,
418        error: Option<QueueWedgeError>,
419    ) -> Result<(), Self::Error>;
420
421    /// Loads all the rooms which have any pending requests in their send queue.
422    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error>;
423
424    /// Add a new entry to the list of dependent send queue requests for a
425    /// parent request.
426    async fn save_dependent_queued_request(
427        &self,
428        room_id: &RoomId,
429        parent_txn_id: &TransactionId,
430        own_txn_id: ChildTransactionId,
431        created_at: MilliSecondsSinceUnixEpoch,
432        content: DependentQueuedRequestKind,
433    ) -> Result<(), Self::Error>;
434
435    /// Mark a set of dependent send queue requests as ready, using a key
436    /// identifying the homeserver's response.
437    ///
438    /// ⚠ Beware! There's no verification applied that the parent key type is
439    /// compatible with the dependent event type. The invalid state may be
440    /// lazily filtered out in `load_dependent_queued_requests`.
441    ///
442    /// Returns the number of updated requests.
443    async fn mark_dependent_queued_requests_as_ready(
444        &self,
445        room_id: &RoomId,
446        parent_txn_id: &TransactionId,
447        sent_parent_key: SentRequestKey,
448    ) -> Result<usize, Self::Error>;
449
450    /// Update a dependent send queue request with the new content.
451    ///
452    /// Returns true if the request was found and could be updated.
453    async fn update_dependent_queued_request(
454        &self,
455        room_id: &RoomId,
456        own_transaction_id: &ChildTransactionId,
457        new_content: DependentQueuedRequestKind,
458    ) -> Result<bool, Self::Error>;
459
460    /// Remove a specific dependent send queue request by id.
461    ///
462    /// Returns true if the dependent send queue request has been indeed
463    /// removed.
464    async fn remove_dependent_queued_request(
465        &self,
466        room: &RoomId,
467        own_txn_id: &ChildTransactionId,
468    ) -> Result<bool, Self::Error>;
469
470    /// List all the dependent send queue requests.
471    ///
472    /// This returns absolutely all the dependent send queue requests, whether
473    /// they have a parent event id or not. As a contract for implementors, they
474    /// must be returned in insertion order.
475    async fn load_dependent_queued_requests(
476        &self,
477        room: &RoomId,
478    ) -> Result<Vec<DependentQueuedRequest>, Self::Error>;
479
480    /// Inserts or updates multiple thread subscriptions.
481    ///
482    /// If the new thread subscription hasn't set a bumpstamp, and there was a
483    /// previous subscription in the database with a bumpstamp, the existing
484    /// bumpstamp is kept.
485    ///
486    /// If the new thread subscription has a bumpstamp that's lower than or
487    /// equal to a previous one, the existing subscription is kept, i.e. this
488    /// method must have no effect.
489    async fn upsert_thread_subscriptions(
490        &self,
491        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
492    ) -> Result<(), Self::Error>;
493
494    /// Remove a previous thread subscription for a given room and thread.
495    ///
496    /// Note: removing an unknown thread subscription is a no-op.
497    async fn remove_thread_subscription(
498        &self,
499        room: &RoomId,
500        thread_id: &EventId,
501    ) -> Result<(), Self::Error>;
502
503    /// Loads the current thread subscription for a given room and thread.
504    ///
505    /// Returns `None` if there was no entry for the given room/thread pair.
506    async fn load_thread_subscription(
507        &self,
508        room: &RoomId,
509        thread_id: &EventId,
510    ) -> Result<Option<StoredThreadSubscription>, Self::Error>;
511
512    /// Get a user's global profile from the store.
513    ///
514    /// Global profiles are persisted as part of [`StateStore::save_changes`],
515    /// from the [`StateChanges::global_profiles`] field, following the MSC4262
516    /// update pattern: fields with an explicit `null` value are removed, while
517    /// fields not present are left unchanged.
518    ///
519    /// Returns `None` if there was no stored global profile for the given user.
520    async fn get_global_profile(
521        &self,
522        user_id: &UserId,
523    ) -> Result<Option<UserProfile>, Self::Error>;
524
525    /// Get the global profiles for the given users from the store.
526    ///
527    /// See [`StateStore::get_global_profile`] for more details. Users without a
528    /// stored global profile are absent from the returned map.
529    async fn get_global_profiles<'a>(
530        &self,
531        user_ids: &'a [OwnedUserId],
532    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error>;
533
534    /// Get which of the given users' global profiles can be fetched directly,
535    /// rather than waiting for them to come via /sync.
536    ///
537    /// These are the users without a stored global profile, and whose profile
538    /// isn't marked as unavailable, see
539    /// [`StateChanges::unavailable_global_profiles`].
540    async fn get_missing_global_profiles<'a>(
541        &self,
542        user_ids: &'a [OwnedUserId],
543    ) -> Result<Vec<&'a UserId>, Self::Error>;
544
545    /// Close the store, releasing all held resources (database connections,
546    /// file descriptors, file locks).
547    ///
548    /// In-flight operations complete before this method returns. After it
549    /// returns, operations will fail until [`Self::reopen()`] is called.
550    async fn close(&self) -> Result<(), Self::Error>;
551
552    /// Reopen the store after a [`Self::close()`], re-acquiring database
553    /// connections.
554    async fn reopen(&self) -> Result<(), Self::Error>;
555
556    /// Perform database optimizations if any are available, i.e. vacuuming in
557    /// SQLite.
558    ///
559    /// /// **Warning:** this was added to check if SQLite fragmentation was the
560    /// source of performance issues, **DO NOT use in production**.
561    #[doc(hidden)]
562    async fn optimize(&self) -> Result<(), Self::Error>;
563
564    /// Returns the size of the store in bytes, if known.
565    async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
566}
567
568#[cfg_attr(target_family = "wasm", async_trait(?Send))]
569#[cfg_attr(not(target_family = "wasm"), async_trait)]
570impl<T: StateStore> StateStore for &T {
571    type Error = T::Error;
572
573    async fn get_kv_data(
574        &self,
575        key: StateStoreDataKey<'_>,
576    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
577        (*self).get_kv_data(key).await
578    }
579
580    async fn set_kv_data(
581        &self,
582        key: StateStoreDataKey<'_>,
583        value: StateStoreDataValue,
584    ) -> Result<(), Self::Error> {
585        (*self).set_kv_data(key, value).await
586    }
587
588    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
589        (*self).remove_kv_data(key).await
590    }
591
592    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
593        (*self).save_changes(changes).await
594    }
595
596    async fn get_presence_event(
597        &self,
598        user_id: &UserId,
599    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
600        (*self).get_presence_event(user_id).await
601    }
602
603    async fn get_presence_events(
604        &self,
605        user_ids: &[OwnedUserId],
606    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
607        (*self).get_presence_events(user_ids).await
608    }
609
610    async fn get_state_event(
611        &self,
612        room_id: &RoomId,
613        event_type: StateEventType,
614        state_key: &str,
615    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
616        (*self).get_state_event(room_id, event_type, state_key).await
617    }
618
619    async fn get_state_events(
620        &self,
621        room_id: &RoomId,
622        event_type: StateEventType,
623    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
624        (*self).get_state_events(room_id, event_type).await
625    }
626
627    async fn get_state_events_for_keys(
628        &self,
629        room_id: &RoomId,
630        event_type: StateEventType,
631        state_keys: &[&str],
632    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
633        (*self).get_state_events_for_keys(room_id, event_type, state_keys).await
634    }
635
636    async fn get_profile(
637        &self,
638        room_id: &RoomId,
639        user_id: &UserId,
640    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
641        (*self).get_profile(room_id, user_id).await
642    }
643
644    async fn get_profiles<'a>(
645        &self,
646        room_id: &RoomId,
647        user_ids: &'a [OwnedUserId],
648    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
649        (*self).get_profiles(room_id, user_ids).await
650    }
651
652    async fn get_user_ids(
653        &self,
654        room_id: &RoomId,
655        memberships: RoomMemberships,
656    ) -> Result<Vec<OwnedUserId>, Self::Error> {
657        (*self).get_user_ids(room_id, memberships).await
658    }
659
660    async fn get_room_infos(
661        &self,
662        room_load_settings: &RoomLoadSettings,
663    ) -> Result<Vec<RoomInfo>, Self::Error> {
664        (*self).get_room_infos(room_load_settings).await
665    }
666
667    async fn get_users_with_display_name(
668        &self,
669        room_id: &RoomId,
670        display_name: &DisplayName,
671    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
672        (*self).get_users_with_display_name(room_id, display_name).await
673    }
674
675    async fn get_users_with_display_names<'a>(
676        &self,
677        room_id: &RoomId,
678        display_names: &'a [DisplayName],
679    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
680        (*self).get_users_with_display_names(room_id, display_names).await
681    }
682
683    async fn get_account_data_event(
684        &self,
685        event_type: GlobalAccountDataEventType,
686    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
687        (*self).get_account_data_event(event_type).await
688    }
689
690    async fn get_room_account_data_event(
691        &self,
692        room_id: &RoomId,
693        event_type: RoomAccountDataEventType,
694    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
695        (*self).get_room_account_data_event(room_id, event_type).await
696    }
697
698    async fn get_user_room_receipt_event(
699        &self,
700        room_id: &RoomId,
701        receipt_type: ReceiptType,
702        receipt_thread: &ReceiptThread,
703        user_id: &UserId,
704    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
705        (*self).get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id).await
706    }
707
708    async fn get_event_room_receipt_events(
709        &self,
710        room_id: &RoomId,
711        receipt_type: ReceiptType,
712        receipt_thread: &ReceiptThread,
713        event_id: &EventId,
714    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
715        (*self).get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id).await
716    }
717
718    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
719        (*self).get_custom_value(key).await
720    }
721
722    async fn set_custom_value(
723        &self,
724        key: &[u8],
725        value: Vec<u8>,
726    ) -> Result<Option<Vec<u8>>, Self::Error> {
727        (*self).set_custom_value(key, value).await
728    }
729
730    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
731        (*self).remove_custom_value(key).await
732    }
733
734    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
735        (*self).remove_room(room_id).await
736    }
737
738    async fn save_send_queue_request(
739        &self,
740        room_id: &RoomId,
741        transaction_id: OwnedTransactionId,
742        created_at: MilliSecondsSinceUnixEpoch,
743        request: QueuedRequestKind,
744        priority: usize,
745    ) -> Result<(), Self::Error> {
746        (*self)
747            .save_send_queue_request(room_id, transaction_id, created_at, request, priority)
748            .await
749    }
750
751    async fn update_send_queue_request(
752        &self,
753        room_id: &RoomId,
754        transaction_id: &TransactionId,
755        content: QueuedRequestKind,
756    ) -> Result<bool, Self::Error> {
757        (*self).update_send_queue_request(room_id, transaction_id, content).await
758    }
759
760    async fn remove_send_queue_request(
761        &self,
762        room_id: &RoomId,
763        transaction_id: &TransactionId,
764    ) -> Result<bool, Self::Error> {
765        (*self).remove_send_queue_request(room_id, transaction_id).await
766    }
767
768    async fn load_send_queue_requests(
769        &self,
770        room_id: &RoomId,
771    ) -> Result<Vec<QueuedRequest>, Self::Error> {
772        (*self).load_send_queue_requests(room_id).await
773    }
774
775    async fn update_send_queue_request_status(
776        &self,
777        room_id: &RoomId,
778        transaction_id: &TransactionId,
779        error: Option<QueueWedgeError>,
780    ) -> Result<(), Self::Error> {
781        (*self).update_send_queue_request_status(room_id, transaction_id, error).await
782    }
783
784    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
785        (*self).load_rooms_with_unsent_requests().await
786    }
787
788    async fn save_dependent_queued_request(
789        &self,
790        room_id: &RoomId,
791        parent_txn_id: &TransactionId,
792        own_txn_id: ChildTransactionId,
793        created_at: MilliSecondsSinceUnixEpoch,
794        content: DependentQueuedRequestKind,
795    ) -> Result<(), Self::Error> {
796        (*self)
797            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
798            .await
799    }
800
801    async fn mark_dependent_queued_requests_as_ready(
802        &self,
803        room_id: &RoomId,
804        parent_txn_id: &TransactionId,
805        sent_parent_key: SentRequestKey,
806    ) -> Result<usize, Self::Error> {
807        (*self)
808            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
809            .await
810    }
811
812    async fn update_dependent_queued_request(
813        &self,
814        room_id: &RoomId,
815        own_transaction_id: &ChildTransactionId,
816        new_content: DependentQueuedRequestKind,
817    ) -> Result<bool, Self::Error> {
818        (*self).update_dependent_queued_request(room_id, own_transaction_id, new_content).await
819    }
820
821    async fn remove_dependent_queued_request(
822        &self,
823        room: &RoomId,
824        own_txn_id: &ChildTransactionId,
825    ) -> Result<bool, Self::Error> {
826        (*self).remove_dependent_queued_request(room, own_txn_id).await
827    }
828
829    async fn load_dependent_queued_requests(
830        &self,
831        room: &RoomId,
832    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
833        (*self).load_dependent_queued_requests(room).await
834    }
835
836    async fn upsert_thread_subscriptions(
837        &self,
838        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
839    ) -> Result<(), Self::Error> {
840        (*self).upsert_thread_subscriptions(updates).await
841    }
842
843    async fn remove_thread_subscription(
844        &self,
845        room: &RoomId,
846        thread_id: &EventId,
847    ) -> Result<(), Self::Error> {
848        (*self).remove_thread_subscription(room, thread_id).await
849    }
850
851    async fn load_thread_subscription(
852        &self,
853        room: &RoomId,
854        thread_id: &EventId,
855    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
856        (*self).load_thread_subscription(room, thread_id).await
857    }
858
859    async fn get_global_profile(
860        &self,
861        user_id: &UserId,
862    ) -> Result<Option<UserProfile>, Self::Error> {
863        (*self).get_global_profile(user_id).await
864    }
865
866    async fn get_global_profiles<'a>(
867        &self,
868        user_ids: &'a [OwnedUserId],
869    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
870        (*self).get_global_profiles(user_ids).await
871    }
872
873    async fn get_missing_global_profiles<'a>(
874        &self,
875        user_ids: &'a [OwnedUserId],
876    ) -> Result<Vec<&'a UserId>, Self::Error> {
877        (*self).get_missing_global_profiles(user_ids).await
878    }
879
880    async fn close(&self) -> Result<(), Self::Error> {
881        (*self).close().await
882    }
883
884    async fn reopen(&self) -> Result<(), Self::Error> {
885        (*self).reopen().await
886    }
887
888    async fn optimize(&self) -> Result<(), Self::Error> {
889        (*self).optimize().await
890    }
891
892    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
893        (*self).get_size().await
894    }
895}
896
897#[cfg_attr(target_family = "wasm", async_trait(?Send))]
898#[cfg_attr(not(target_family = "wasm"), async_trait)]
899impl<T: StateStore + ?Sized> StateStore for Arc<T> {
900    type Error = T::Error;
901
902    async fn get_kv_data(
903        &self,
904        key: StateStoreDataKey<'_>,
905    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
906        self.deref().get_kv_data(key).await
907    }
908
909    async fn set_kv_data(
910        &self,
911        key: StateStoreDataKey<'_>,
912        value: StateStoreDataValue,
913    ) -> Result<(), Self::Error> {
914        self.deref().set_kv_data(key, value).await
915    }
916
917    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
918        self.deref().remove_kv_data(key).await
919    }
920
921    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
922        self.deref().save_changes(changes).await
923    }
924
925    async fn get_presence_event(
926        &self,
927        user_id: &UserId,
928    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
929        self.deref().get_presence_event(user_id).await
930    }
931
932    async fn get_presence_events(
933        &self,
934        user_ids: &[OwnedUserId],
935    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
936        self.deref().get_presence_events(user_ids).await
937    }
938
939    async fn get_state_event(
940        &self,
941        room_id: &RoomId,
942        event_type: StateEventType,
943        state_key: &str,
944    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
945        self.deref().get_state_event(room_id, event_type, state_key).await
946    }
947
948    async fn get_state_events(
949        &self,
950        room_id: &RoomId,
951        event_type: StateEventType,
952    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
953        self.deref().get_state_events(room_id, event_type).await
954    }
955
956    async fn get_state_events_for_keys(
957        &self,
958        room_id: &RoomId,
959        event_type: StateEventType,
960        state_keys: &[&str],
961    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
962        self.deref().get_state_events_for_keys(room_id, event_type, state_keys).await
963    }
964
965    async fn get_profile(
966        &self,
967        room_id: &RoomId,
968        user_id: &UserId,
969    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
970        self.deref().get_profile(room_id, user_id).await
971    }
972
973    async fn get_profiles<'a>(
974        &self,
975        room_id: &RoomId,
976        user_ids: &'a [OwnedUserId],
977    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
978        self.deref().get_profiles(room_id, user_ids).await
979    }
980
981    async fn get_user_ids(
982        &self,
983        room_id: &RoomId,
984        memberships: RoomMemberships,
985    ) -> Result<Vec<OwnedUserId>, Self::Error> {
986        self.deref().get_user_ids(room_id, memberships).await
987    }
988
989    async fn get_room_infos(
990        &self,
991        room_load_settings: &RoomLoadSettings,
992    ) -> Result<Vec<RoomInfo>, Self::Error> {
993        self.deref().get_room_infos(room_load_settings).await
994    }
995
996    async fn get_users_with_display_name(
997        &self,
998        room_id: &RoomId,
999        display_name: &DisplayName,
1000    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
1001        self.deref().get_users_with_display_name(room_id, display_name).await
1002    }
1003
1004    async fn get_users_with_display_names<'a>(
1005        &self,
1006        room_id: &RoomId,
1007        display_names: &'a [DisplayName],
1008    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
1009        self.deref().get_users_with_display_names(room_id, display_names).await
1010    }
1011
1012    async fn get_account_data_event(
1013        &self,
1014        event_type: GlobalAccountDataEventType,
1015    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
1016        self.deref().get_account_data_event(event_type).await
1017    }
1018
1019    async fn get_room_account_data_event(
1020        &self,
1021        room_id: &RoomId,
1022        event_type: RoomAccountDataEventType,
1023    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
1024        self.deref().get_room_account_data_event(room_id, event_type).await
1025    }
1026
1027    async fn get_user_room_receipt_event(
1028        &self,
1029        room_id: &RoomId,
1030        receipt_type: ReceiptType,
1031        receipt_thread: &ReceiptThread,
1032        user_id: &UserId,
1033    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
1034        self.deref()
1035            .get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id)
1036            .await
1037    }
1038
1039    async fn get_event_room_receipt_events(
1040        &self,
1041        room_id: &RoomId,
1042        receipt_type: ReceiptType,
1043        receipt_thread: &ReceiptThread,
1044        event_id: &EventId,
1045    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
1046        self.deref()
1047            .get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id)
1048            .await
1049    }
1050
1051    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1052        self.deref().get_custom_value(key).await
1053    }
1054
1055    async fn set_custom_value(
1056        &self,
1057        key: &[u8],
1058        value: Vec<u8>,
1059    ) -> Result<Option<Vec<u8>>, Self::Error> {
1060        self.deref().set_custom_value(key, value).await
1061    }
1062
1063    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1064        self.deref().remove_custom_value(key).await
1065    }
1066
1067    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
1068        self.deref().remove_room(room_id).await
1069    }
1070
1071    async fn save_send_queue_request(
1072        &self,
1073        room_id: &RoomId,
1074        transaction_id: OwnedTransactionId,
1075        created_at: MilliSecondsSinceUnixEpoch,
1076        request: QueuedRequestKind,
1077        priority: usize,
1078    ) -> Result<(), Self::Error> {
1079        self.deref()
1080            .save_send_queue_request(room_id, transaction_id, created_at, request, priority)
1081            .await
1082    }
1083
1084    async fn update_send_queue_request(
1085        &self,
1086        room_id: &RoomId,
1087        transaction_id: &TransactionId,
1088        content: QueuedRequestKind,
1089    ) -> Result<bool, Self::Error> {
1090        self.deref().update_send_queue_request(room_id, transaction_id, content).await
1091    }
1092
1093    async fn remove_send_queue_request(
1094        &self,
1095        room_id: &RoomId,
1096        transaction_id: &TransactionId,
1097    ) -> Result<bool, Self::Error> {
1098        self.deref().remove_send_queue_request(room_id, transaction_id).await
1099    }
1100
1101    async fn load_send_queue_requests(
1102        &self,
1103        room_id: &RoomId,
1104    ) -> Result<Vec<QueuedRequest>, Self::Error> {
1105        self.deref().load_send_queue_requests(room_id).await
1106    }
1107
1108    async fn update_send_queue_request_status(
1109        &self,
1110        room_id: &RoomId,
1111        transaction_id: &TransactionId,
1112        error: Option<QueueWedgeError>,
1113    ) -> Result<(), Self::Error> {
1114        self.deref().update_send_queue_request_status(room_id, transaction_id, error).await
1115    }
1116
1117    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
1118        self.deref().load_rooms_with_unsent_requests().await
1119    }
1120
1121    async fn save_dependent_queued_request(
1122        &self,
1123        room_id: &RoomId,
1124        parent_txn_id: &TransactionId,
1125        own_txn_id: ChildTransactionId,
1126        created_at: MilliSecondsSinceUnixEpoch,
1127        content: DependentQueuedRequestKind,
1128    ) -> Result<(), Self::Error> {
1129        self.deref()
1130            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
1131            .await
1132    }
1133
1134    async fn mark_dependent_queued_requests_as_ready(
1135        &self,
1136        room_id: &RoomId,
1137        parent_txn_id: &TransactionId,
1138        sent_parent_key: SentRequestKey,
1139    ) -> Result<usize, Self::Error> {
1140        self.deref()
1141            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
1142            .await
1143    }
1144
1145    async fn update_dependent_queued_request(
1146        &self,
1147        room_id: &RoomId,
1148        own_transaction_id: &ChildTransactionId,
1149        new_content: DependentQueuedRequestKind,
1150    ) -> Result<bool, Self::Error> {
1151        self.deref().update_dependent_queued_request(room_id, own_transaction_id, new_content).await
1152    }
1153
1154    async fn remove_dependent_queued_request(
1155        &self,
1156        room: &RoomId,
1157        own_txn_id: &ChildTransactionId,
1158    ) -> Result<bool, Self::Error> {
1159        self.deref().remove_dependent_queued_request(room, own_txn_id).await
1160    }
1161
1162    async fn load_dependent_queued_requests(
1163        &self,
1164        room: &RoomId,
1165    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
1166        self.deref().load_dependent_queued_requests(room).await
1167    }
1168
1169    async fn upsert_thread_subscriptions(
1170        &self,
1171        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
1172    ) -> Result<(), Self::Error> {
1173        self.deref().upsert_thread_subscriptions(updates).await
1174    }
1175
1176    async fn remove_thread_subscription(
1177        &self,
1178        room: &RoomId,
1179        thread_id: &EventId,
1180    ) -> Result<(), Self::Error> {
1181        self.deref().remove_thread_subscription(room, thread_id).await
1182    }
1183
1184    async fn load_thread_subscription(
1185        &self,
1186        room: &RoomId,
1187        thread_id: &EventId,
1188    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
1189        self.deref().load_thread_subscription(room, thread_id).await
1190    }
1191
1192    async fn get_global_profile(
1193        &self,
1194        user_id: &UserId,
1195    ) -> Result<Option<UserProfile>, Self::Error> {
1196        self.deref().get_global_profile(user_id).await
1197    }
1198
1199    async fn get_global_profiles<'a>(
1200        &self,
1201        user_ids: &'a [OwnedUserId],
1202    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
1203        self.deref().get_global_profiles(user_ids).await
1204    }
1205
1206    async fn get_missing_global_profiles<'a>(
1207        &self,
1208        user_ids: &'a [OwnedUserId],
1209    ) -> Result<Vec<&'a UserId>, Self::Error> {
1210        self.deref().get_missing_global_profiles(user_ids).await
1211    }
1212
1213    async fn close(&self) -> Result<(), Self::Error> {
1214        self.deref().close().await
1215    }
1216
1217    async fn reopen(&self) -> Result<(), Self::Error> {
1218        self.deref().reopen().await
1219    }
1220
1221    async fn optimize(&self) -> Result<(), Self::Error> {
1222        self.deref().optimize().await
1223    }
1224
1225    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
1226        self.deref().get_size().await
1227    }
1228}
1229
1230#[repr(transparent)]
1231struct EraseStateStoreError<T>(T);
1232
1233#[cfg(not(tarpaulin_include))]
1234impl<T: fmt::Debug> fmt::Debug for EraseStateStoreError<T> {
1235    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1236        self.0.fmt(f)
1237    }
1238}
1239
1240#[cfg_attr(target_family = "wasm", async_trait(?Send))]
1241#[cfg_attr(not(target_family = "wasm"), async_trait)]
1242impl<T: StateStore> StateStore for EraseStateStoreError<T> {
1243    type Error = StoreError;
1244
1245    async fn get_kv_data(
1246        &self,
1247        key: StateStoreDataKey<'_>,
1248    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
1249        self.0.get_kv_data(key).await.map_err(Into::into)
1250    }
1251
1252    async fn set_kv_data(
1253        &self,
1254        key: StateStoreDataKey<'_>,
1255        value: StateStoreDataValue,
1256    ) -> Result<(), Self::Error> {
1257        self.0.set_kv_data(key, value).await.map_err(Into::into)
1258    }
1259
1260    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
1261        self.0.remove_kv_data(key).await.map_err(Into::into)
1262    }
1263
1264    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
1265        self.0.save_changes(changes).await.map_err(Into::into)
1266    }
1267
1268    async fn get_presence_event(
1269        &self,
1270        user_id: &UserId,
1271    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
1272        self.0.get_presence_event(user_id).await.map_err(Into::into)
1273    }
1274
1275    async fn get_presence_events(
1276        &self,
1277        user_ids: &[OwnedUserId],
1278    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
1279        self.0.get_presence_events(user_ids).await.map_err(Into::into)
1280    }
1281
1282    async fn get_state_event(
1283        &self,
1284        room_id: &RoomId,
1285        event_type: StateEventType,
1286        state_key: &str,
1287    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
1288        self.0.get_state_event(room_id, event_type, state_key).await.map_err(Into::into)
1289    }
1290
1291    async fn get_state_events(
1292        &self,
1293        room_id: &RoomId,
1294        event_type: StateEventType,
1295    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1296        self.0.get_state_events(room_id, event_type).await.map_err(Into::into)
1297    }
1298
1299    async fn get_state_events_for_keys(
1300        &self,
1301        room_id: &RoomId,
1302        event_type: StateEventType,
1303        state_keys: &[&str],
1304    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1305        self.0.get_state_events_for_keys(room_id, event_type, state_keys).await.map_err(Into::into)
1306    }
1307
1308    async fn get_profile(
1309        &self,
1310        room_id: &RoomId,
1311        user_id: &UserId,
1312    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
1313        self.0.get_profile(room_id, user_id).await.map_err(Into::into)
1314    }
1315
1316    async fn get_profiles<'a>(
1317        &self,
1318        room_id: &RoomId,
1319        user_ids: &'a [OwnedUserId],
1320    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
1321        self.0.get_profiles(room_id, user_ids).await.map_err(Into::into)
1322    }
1323
1324    async fn get_user_ids(
1325        &self,
1326        room_id: &RoomId,
1327        memberships: RoomMemberships,
1328    ) -> Result<Vec<OwnedUserId>, Self::Error> {
1329        self.0.get_user_ids(room_id, memberships).await.map_err(Into::into)
1330    }
1331
1332    async fn get_room_infos(
1333        &self,
1334        room_load_settings: &RoomLoadSettings,
1335    ) -> Result<Vec<RoomInfo>, Self::Error> {
1336        self.0.get_room_infos(room_load_settings).await.map_err(Into::into)
1337    }
1338
1339    async fn get_users_with_display_name(
1340        &self,
1341        room_id: &RoomId,
1342        display_name: &DisplayName,
1343    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
1344        self.0.get_users_with_display_name(room_id, display_name).await.map_err(Into::into)
1345    }
1346
1347    async fn get_users_with_display_names<'a>(
1348        &self,
1349        room_id: &RoomId,
1350        display_names: &'a [DisplayName],
1351    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
1352        self.0.get_users_with_display_names(room_id, display_names).await.map_err(Into::into)
1353    }
1354
1355    async fn get_account_data_event(
1356        &self,
1357        event_type: GlobalAccountDataEventType,
1358    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
1359        self.0.get_account_data_event(event_type).await.map_err(Into::into)
1360    }
1361
1362    async fn get_room_account_data_event(
1363        &self,
1364        room_id: &RoomId,
1365        event_type: RoomAccountDataEventType,
1366    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
1367        self.0.get_room_account_data_event(room_id, event_type).await.map_err(Into::into)
1368    }
1369
1370    async fn get_user_room_receipt_event(
1371        &self,
1372        room_id: &RoomId,
1373        receipt_type: ReceiptType,
1374        receipt_thread: &ReceiptThread,
1375        user_id: &UserId,
1376    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
1377        self.0
1378            .get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id)
1379            .await
1380            .map_err(Into::into)
1381    }
1382
1383    async fn get_event_room_receipt_events(
1384        &self,
1385        room_id: &RoomId,
1386        receipt_type: ReceiptType,
1387        receipt_thread: &ReceiptThread,
1388        event_id: &EventId,
1389    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
1390        self.0
1391            .get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id)
1392            .await
1393            .map_err(Into::into)
1394    }
1395
1396    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1397        self.0.get_custom_value(key).await.map_err(Into::into)
1398    }
1399
1400    async fn set_custom_value(
1401        &self,
1402        key: &[u8],
1403        value: Vec<u8>,
1404    ) -> Result<Option<Vec<u8>>, Self::Error> {
1405        self.0.set_custom_value(key, value).await.map_err(Into::into)
1406    }
1407
1408    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1409        self.0.remove_custom_value(key).await.map_err(Into::into)
1410    }
1411
1412    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
1413        self.0.remove_room(room_id).await.map_err(Into::into)
1414    }
1415
1416    async fn save_send_queue_request(
1417        &self,
1418        room_id: &RoomId,
1419        transaction_id: OwnedTransactionId,
1420        created_at: MilliSecondsSinceUnixEpoch,
1421        content: QueuedRequestKind,
1422        priority: usize,
1423    ) -> Result<(), Self::Error> {
1424        self.0
1425            .save_send_queue_request(room_id, transaction_id, created_at, content, priority)
1426            .await
1427            .map_err(Into::into)
1428    }
1429
1430    async fn update_send_queue_request(
1431        &self,
1432        room_id: &RoomId,
1433        transaction_id: &TransactionId,
1434        content: QueuedRequestKind,
1435    ) -> Result<bool, Self::Error> {
1436        self.0.update_send_queue_request(room_id, transaction_id, content).await.map_err(Into::into)
1437    }
1438
1439    async fn remove_send_queue_request(
1440        &self,
1441        room_id: &RoomId,
1442        transaction_id: &TransactionId,
1443    ) -> Result<bool, Self::Error> {
1444        self.0.remove_send_queue_request(room_id, transaction_id).await.map_err(Into::into)
1445    }
1446
1447    async fn load_send_queue_requests(
1448        &self,
1449        room_id: &RoomId,
1450    ) -> Result<Vec<QueuedRequest>, Self::Error> {
1451        self.0.load_send_queue_requests(room_id).await.map_err(Into::into)
1452    }
1453
1454    async fn update_send_queue_request_status(
1455        &self,
1456        room_id: &RoomId,
1457        transaction_id: &TransactionId,
1458        error: Option<QueueWedgeError>,
1459    ) -> Result<(), Self::Error> {
1460        self.0
1461            .update_send_queue_request_status(room_id, transaction_id, error)
1462            .await
1463            .map_err(Into::into)
1464    }
1465
1466    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
1467        self.0.load_rooms_with_unsent_requests().await.map_err(Into::into)
1468    }
1469
1470    async fn save_dependent_queued_request(
1471        &self,
1472        room_id: &RoomId,
1473        parent_txn_id: &TransactionId,
1474        own_txn_id: ChildTransactionId,
1475        created_at: MilliSecondsSinceUnixEpoch,
1476        content: DependentQueuedRequestKind,
1477    ) -> Result<(), Self::Error> {
1478        self.0
1479            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
1480            .await
1481            .map_err(Into::into)
1482    }
1483
1484    async fn mark_dependent_queued_requests_as_ready(
1485        &self,
1486        room_id: &RoomId,
1487        parent_txn_id: &TransactionId,
1488        sent_parent_key: SentRequestKey,
1489    ) -> Result<usize, Self::Error> {
1490        self.0
1491            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
1492            .await
1493            .map_err(Into::into)
1494    }
1495
1496    async fn remove_dependent_queued_request(
1497        &self,
1498        room_id: &RoomId,
1499        own_txn_id: &ChildTransactionId,
1500    ) -> Result<bool, Self::Error> {
1501        self.0.remove_dependent_queued_request(room_id, own_txn_id).await.map_err(Into::into)
1502    }
1503
1504    async fn load_dependent_queued_requests(
1505        &self,
1506        room_id: &RoomId,
1507    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
1508        self.0.load_dependent_queued_requests(room_id).await.map_err(Into::into)
1509    }
1510
1511    async fn update_dependent_queued_request(
1512        &self,
1513        room_id: &RoomId,
1514        own_transaction_id: &ChildTransactionId,
1515        new_content: DependentQueuedRequestKind,
1516    ) -> Result<bool, Self::Error> {
1517        self.0
1518            .update_dependent_queued_request(room_id, own_transaction_id, new_content)
1519            .await
1520            .map_err(Into::into)
1521    }
1522
1523    async fn upsert_thread_subscriptions(
1524        &self,
1525        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
1526    ) -> Result<(), Self::Error> {
1527        self.0.upsert_thread_subscriptions(updates).await.map_err(Into::into)
1528    }
1529
1530    async fn load_thread_subscription(
1531        &self,
1532        room: &RoomId,
1533        thread_id: &EventId,
1534    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
1535        self.0.load_thread_subscription(room, thread_id).await.map_err(Into::into)
1536    }
1537
1538    async fn remove_thread_subscription(
1539        &self,
1540        room: &RoomId,
1541        thread_id: &EventId,
1542    ) -> Result<(), Self::Error> {
1543        self.0.remove_thread_subscription(room, thread_id).await.map_err(Into::into)
1544    }
1545
1546    async fn get_global_profile(
1547        &self,
1548        user_id: &UserId,
1549    ) -> Result<Option<UserProfile>, Self::Error> {
1550        self.0.get_global_profile(user_id).await.map_err(Into::into)
1551    }
1552
1553    async fn get_global_profiles<'a>(
1554        &self,
1555        user_ids: &'a [OwnedUserId],
1556    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
1557        self.0.get_global_profiles(user_ids).await.map_err(Into::into)
1558    }
1559
1560    async fn get_missing_global_profiles<'a>(
1561        &self,
1562        user_ids: &'a [OwnedUserId],
1563    ) -> Result<Vec<&'a UserId>, Self::Error> {
1564        self.0.get_missing_global_profiles(user_ids).await.map_err(Into::into)
1565    }
1566
1567    async fn close(&self) -> Result<(), Self::Error> {
1568        self.0.close().await.map_err(Into::into)
1569    }
1570
1571    async fn reopen(&self) -> Result<(), Self::Error> {
1572        self.0.reopen().await.map_err(Into::into)
1573    }
1574
1575    async fn optimize(&self) -> Result<(), Self::Error> {
1576        self.0.optimize().await.map_err(Into::into)
1577    }
1578
1579    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
1580        self.0.get_size().await.map_err(Into::into)
1581    }
1582}
1583
1584/// A wrapper around a [`StateStore`] that supports synchronizing calls to
1585/// [`StateStore::save_changes`].
1586#[derive(Debug, Clone)]
1587pub struct SaveLockedStateStore<T = Arc<DynStateStore>> {
1588    store: T,
1589    lock: Arc<Mutex<()>>,
1590}
1591
1592/// An error type that represents a scenario where a [`MutexGuard`] provided to
1593/// a function does not reference the underlying [`Mutex`] in the enclosing
1594/// [`SaveLockedStateStore`].
1595#[derive(Debug, Error)]
1596#[error("a mutex guard was provided, but it does not reference the correct mutex")]
1597pub struct IncorrectMutexGuardError;
1598
1599impl From<IncorrectMutexGuardError> for StoreError {
1600    fn from(value: IncorrectMutexGuardError) -> Self {
1601        Self::backend(value)
1602    }
1603}
1604
1605impl<T> SaveLockedStateStore<T> {
1606    /// Creates a new [`SaveLockedStateStore`] with the provided store.
1607    pub fn new(store: T) -> Self {
1608        Self { store, lock: Arc::new(Mutex::new(())) }
1609    }
1610
1611    /// Returns a reference to the underlying [`Mutex`] used to synchronize
1612    /// calls to [`StateStore::save_changes`].
1613    pub fn lock(&self) -> &Mutex<()> {
1614        self.lock.as_ref()
1615    }
1616}
1617
1618impl<T: StateStore> SaveLockedStateStore<T> {
1619    /// Provides a means of calling [`StateStore::save_changes`] when the caller
1620    /// has already acquired the underlying [`Mutex`]. Returns an error if the
1621    /// [`MutexGuard`] provided does not reference the underlying [`Mutex`].
1622    pub async fn save_changes_with_guard(
1623        &self,
1624        guard: &MutexGuard<'_, ()>,
1625        changes: &StateChanges,
1626    ) -> Result<(), StoreError> {
1627        if !std::ptr::eq(MutexGuard::mutex(guard), self.lock()) {
1628            Err(IncorrectMutexGuardError.into())
1629        } else {
1630            self.store.save_changes(changes).await.map_err(Into::into)
1631        }
1632    }
1633
1634    /// Provides a means of calling [`StateStore::remove_room`] when the caller
1635    /// has already acquired the underlying [`Mutex`]. Returns an error if the
1636    /// [`MutexGuard`] provided does not reference the underlying [`Mutex`].
1637    pub async fn remove_room_with_guard(
1638        &self,
1639        guard: &MutexGuard<'_, ()>,
1640        room_id: &RoomId,
1641    ) -> Result<(), StoreError> {
1642        if !std::ptr::eq(MutexGuard::mutex(guard), self.lock()) {
1643            Err(IncorrectMutexGuardError.into())
1644        } else {
1645            self.store.remove_room(room_id).await.map_err(Into::into)
1646        }
1647    }
1648}
1649
1650#[cfg_attr(target_family = "wasm", async_trait(?Send))]
1651#[cfg_attr(not(target_family = "wasm"), async_trait)]
1652impl<T: StateStore> StateStore for SaveLockedStateStore<T> {
1653    type Error = T::Error;
1654
1655    async fn get_kv_data(
1656        &self,
1657        key: StateStoreDataKey<'_>,
1658    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
1659        self.store.get_kv_data(key).await
1660    }
1661
1662    async fn set_kv_data(
1663        &self,
1664        key: StateStoreDataKey<'_>,
1665        value: StateStoreDataValue,
1666    ) -> Result<(), Self::Error> {
1667        self.store.set_kv_data(key, value).await
1668    }
1669
1670    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
1671        self.store.remove_kv_data(key).await
1672    }
1673
1674    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
1675        let _guard = self.lock.lock().await;
1676        self.store.save_changes(changes).await
1677    }
1678
1679    async fn get_presence_event(
1680        &self,
1681        user_id: &UserId,
1682    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
1683        self.store.get_presence_event(user_id).await
1684    }
1685
1686    async fn get_presence_events(
1687        &self,
1688        user_ids: &[OwnedUserId],
1689    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
1690        self.store.get_presence_events(user_ids).await
1691    }
1692
1693    async fn get_state_event(
1694        &self,
1695        room_id: &RoomId,
1696        event_type: StateEventType,
1697        state_key: &str,
1698    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
1699        self.store.get_state_event(room_id, event_type, state_key).await
1700    }
1701
1702    async fn get_state_events(
1703        &self,
1704        room_id: &RoomId,
1705        event_type: StateEventType,
1706    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1707        self.store.get_state_events(room_id, event_type).await
1708    }
1709
1710    async fn get_state_events_for_keys(
1711        &self,
1712        room_id: &RoomId,
1713        event_type: StateEventType,
1714        state_keys: &[&str],
1715    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1716        self.store.get_state_events_for_keys(room_id, event_type, state_keys).await
1717    }
1718
1719    async fn get_profile(
1720        &self,
1721        room_id: &RoomId,
1722        user_id: &UserId,
1723    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
1724        self.store.get_profile(room_id, user_id).await
1725    }
1726
1727    async fn get_profiles<'a>(
1728        &self,
1729        room_id: &RoomId,
1730        user_ids: &'a [OwnedUserId],
1731    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
1732        self.store.get_profiles(room_id, user_ids).await
1733    }
1734
1735    async fn get_user_ids(
1736        &self,
1737        room_id: &RoomId,
1738        memberships: RoomMemberships,
1739    ) -> Result<Vec<OwnedUserId>, Self::Error> {
1740        self.store.get_user_ids(room_id, memberships).await
1741    }
1742
1743    async fn get_room_infos(
1744        &self,
1745        room_load_settings: &RoomLoadSettings,
1746    ) -> Result<Vec<RoomInfo>, Self::Error> {
1747        self.store.get_room_infos(room_load_settings).await
1748    }
1749
1750    async fn get_users_with_display_name(
1751        &self,
1752        room_id: &RoomId,
1753        display_name: &DisplayName,
1754    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
1755        self.store.get_users_with_display_name(room_id, display_name).await
1756    }
1757
1758    async fn get_users_with_display_names<'a>(
1759        &self,
1760        room_id: &RoomId,
1761        display_names: &'a [DisplayName],
1762    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
1763        self.store.get_users_with_display_names(room_id, display_names).await
1764    }
1765
1766    async fn get_account_data_event(
1767        &self,
1768        event_type: GlobalAccountDataEventType,
1769    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
1770        self.store.get_account_data_event(event_type).await
1771    }
1772
1773    async fn get_room_account_data_event(
1774        &self,
1775        room_id: &RoomId,
1776        event_type: RoomAccountDataEventType,
1777    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
1778        self.store.get_room_account_data_event(room_id, event_type).await
1779    }
1780
1781    async fn get_user_room_receipt_event(
1782        &self,
1783        room_id: &RoomId,
1784        receipt_type: ReceiptType,
1785        receipt_thread: &ReceiptThread,
1786        user_id: &UserId,
1787    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
1788        self.store.get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id).await
1789    }
1790
1791    async fn get_event_room_receipt_events(
1792        &self,
1793        room_id: &RoomId,
1794        receipt_type: ReceiptType,
1795        receipt_thread: &ReceiptThread,
1796        event_id: &EventId,
1797    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
1798        self.store
1799            .get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id)
1800            .await
1801    }
1802
1803    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1804        self.store.get_custom_value(key).await
1805    }
1806
1807    async fn set_custom_value(
1808        &self,
1809        key: &[u8],
1810        value: Vec<u8>,
1811    ) -> Result<Option<Vec<u8>>, Self::Error> {
1812        self.store.set_custom_value(key, value).await
1813    }
1814
1815    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1816        self.store.remove_custom_value(key).await
1817    }
1818
1819    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
1820        let _guard = self.lock.lock().await;
1821        self.store.remove_room(room_id).await
1822    }
1823
1824    async fn save_send_queue_request(
1825        &self,
1826        room_id: &RoomId,
1827        transaction_id: OwnedTransactionId,
1828        created_at: MilliSecondsSinceUnixEpoch,
1829        request: QueuedRequestKind,
1830        priority: usize,
1831    ) -> Result<(), Self::Error> {
1832        self.store
1833            .save_send_queue_request(room_id, transaction_id, created_at, request, priority)
1834            .await
1835    }
1836
1837    async fn update_send_queue_request(
1838        &self,
1839        room_id: &RoomId,
1840        transaction_id: &TransactionId,
1841        content: QueuedRequestKind,
1842    ) -> Result<bool, Self::Error> {
1843        self.store.update_send_queue_request(room_id, transaction_id, content).await
1844    }
1845
1846    async fn remove_send_queue_request(
1847        &self,
1848        room_id: &RoomId,
1849        transaction_id: &TransactionId,
1850    ) -> Result<bool, Self::Error> {
1851        self.store.remove_send_queue_request(room_id, transaction_id).await
1852    }
1853
1854    async fn load_send_queue_requests(
1855        &self,
1856        room_id: &RoomId,
1857    ) -> Result<Vec<QueuedRequest>, Self::Error> {
1858        self.store.load_send_queue_requests(room_id).await
1859    }
1860
1861    async fn update_send_queue_request_status(
1862        &self,
1863        room_id: &RoomId,
1864        transaction_id: &TransactionId,
1865        error: Option<QueueWedgeError>,
1866    ) -> Result<(), Self::Error> {
1867        self.store.update_send_queue_request_status(room_id, transaction_id, error).await
1868    }
1869
1870    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
1871        self.store.load_rooms_with_unsent_requests().await
1872    }
1873
1874    async fn save_dependent_queued_request(
1875        &self,
1876        room_id: &RoomId,
1877        parent_txn_id: &TransactionId,
1878        own_txn_id: ChildTransactionId,
1879        created_at: MilliSecondsSinceUnixEpoch,
1880        content: DependentQueuedRequestKind,
1881    ) -> Result<(), Self::Error> {
1882        self.store
1883            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
1884            .await
1885    }
1886
1887    async fn mark_dependent_queued_requests_as_ready(
1888        &self,
1889        room_id: &RoomId,
1890        parent_txn_id: &TransactionId,
1891        sent_parent_key: SentRequestKey,
1892    ) -> Result<usize, Self::Error> {
1893        self.store
1894            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
1895            .await
1896    }
1897
1898    async fn update_dependent_queued_request(
1899        &self,
1900        room_id: &RoomId,
1901        own_transaction_id: &ChildTransactionId,
1902        new_content: DependentQueuedRequestKind,
1903    ) -> Result<bool, Self::Error> {
1904        self.store.update_dependent_queued_request(room_id, own_transaction_id, new_content).await
1905    }
1906
1907    async fn remove_dependent_queued_request(
1908        &self,
1909        room: &RoomId,
1910        own_txn_id: &ChildTransactionId,
1911    ) -> Result<bool, Self::Error> {
1912        self.store.remove_dependent_queued_request(room, own_txn_id).await
1913    }
1914
1915    async fn load_dependent_queued_requests(
1916        &self,
1917        room: &RoomId,
1918    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
1919        self.store.load_dependent_queued_requests(room).await
1920    }
1921
1922    async fn upsert_thread_subscriptions(
1923        &self,
1924        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
1925    ) -> Result<(), Self::Error> {
1926        self.store.upsert_thread_subscriptions(updates).await
1927    }
1928
1929    async fn load_thread_subscription(
1930        &self,
1931        room: &RoomId,
1932        thread_id: &EventId,
1933    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
1934        self.store.load_thread_subscription(room, thread_id).await
1935    }
1936
1937    async fn remove_thread_subscription(
1938        &self,
1939        room: &RoomId,
1940        thread_id: &EventId,
1941    ) -> Result<(), Self::Error> {
1942        self.store.remove_thread_subscription(room, thread_id).await
1943    }
1944
1945    async fn get_global_profile(
1946        &self,
1947        user_id: &UserId,
1948    ) -> Result<Option<UserProfile>, Self::Error> {
1949        self.store.get_global_profile(user_id).await
1950    }
1951
1952    async fn get_global_profiles<'a>(
1953        &self,
1954        user_ids: &'a [OwnedUserId],
1955    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
1956        self.store.get_global_profiles(user_ids).await
1957    }
1958
1959    async fn get_missing_global_profiles<'a>(
1960        &self,
1961        user_ids: &'a [OwnedUserId],
1962    ) -> Result<Vec<&'a UserId>, Self::Error> {
1963        self.store.get_missing_global_profiles(user_ids).await
1964    }
1965
1966    async fn close(&self) -> Result<(), Self::Error> {
1967        self.store.close().await
1968    }
1969
1970    async fn reopen(&self) -> Result<(), Self::Error> {
1971        self.store.reopen().await
1972    }
1973
1974    async fn optimize(&self) -> Result<(), Self::Error> {
1975        self.store.optimize().await
1976    }
1977
1978    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
1979        self.store.get_size().await
1980    }
1981}
1982
1983/// Convenience functionality for state stores.
1984#[cfg_attr(target_family = "wasm", async_trait(?Send))]
1985#[cfg_attr(not(target_family = "wasm"), async_trait)]
1986pub trait StateStoreExt: StateStore {
1987    /// Get a specific state event of statically-known type.
1988    ///
1989    /// # Arguments
1990    ///
1991    /// * `room_id` - The id of the room the state event was received for.
1992    async fn get_state_event_static<C>(
1993        &self,
1994        room_id: &RoomId,
1995    ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
1996    where
1997        C: StaticEventContent<IsPrefix = ruma::events::False>
1998            + StaticStateEventContent<StateKey = EmptyStateKey>
1999            + RedactContent,
2000        C::Redacted: RedactedStateEventContent,
2001    {
2002        Ok(self.get_state_event(room_id, C::TYPE.into(), "").await?.map(|raw| raw.cast()))
2003    }
2004
2005    /// Get a specific state event of statically-known type.
2006    ///
2007    /// # Arguments
2008    ///
2009    /// * `room_id` - The id of the room the state event was received for.
2010    async fn get_state_event_static_for_key<C, K>(
2011        &self,
2012        room_id: &RoomId,
2013        state_key: &K,
2014    ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
2015    where
2016        C: StaticEventContent<IsPrefix = ruma::events::False>
2017            + StaticStateEventContent
2018            + RedactContent,
2019        C::StateKey: Borrow<K>,
2020        C::Redacted: RedactedStateEventContent,
2021        K: AsRef<str> + ?Sized + Sync,
2022    {
2023        Ok(self
2024            .get_state_event(room_id, C::TYPE.into(), state_key.as_ref())
2025            .await?
2026            .map(|raw| raw.cast()))
2027    }
2028
2029    /// Get a list of state events of a statically-known type for a given room.
2030    ///
2031    /// # Arguments
2032    ///
2033    /// * `room_id` - The id of the room to find events for.
2034    async fn get_state_events_static<C>(
2035        &self,
2036        room_id: &RoomId,
2037    ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
2038    where
2039        C: StaticEventContent<IsPrefix = ruma::events::False>
2040            + StaticStateEventContent
2041            + RedactContent,
2042        C::Redacted: RedactedStateEventContent,
2043    {
2044        // FIXME: Could be more efficient, if we had streaming store accessor
2045        // functions
2046        Ok(self
2047            .get_state_events(room_id, C::TYPE.into())
2048            .await?
2049            .into_iter()
2050            .map(|raw| raw.cast())
2051            .collect())
2052    }
2053
2054    /// Get a list of state events of a statically-known type for a given room
2055    /// and given state keys.
2056    ///
2057    /// # Arguments
2058    ///
2059    /// - `room_id` - The id of the room to find events for.
2060    /// - `state_keys` - The list of state keys to find.
2061    async fn get_state_events_for_keys_static<'a, C, K, I>(
2062        &self,
2063        room_id: &RoomId,
2064        state_keys: I,
2065    ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
2066    where
2067        C: StaticEventContent<IsPrefix = ruma::events::False>
2068            + StaticStateEventContent
2069            + RedactContent,
2070        C::StateKey: Borrow<K>,
2071        C::Redacted: RedactedStateEventContent,
2072        K: AsRef<str> + Sized + Sync + 'a,
2073        I: IntoIterator<Item = &'a K> + Send,
2074        I::IntoIter: Send,
2075    {
2076        Ok(self
2077            .get_state_events_for_keys(
2078                room_id,
2079                C::TYPE.into(),
2080                &state_keys.into_iter().map(|k| k.as_ref()).collect::<Vec<_>>(),
2081            )
2082            .await?
2083            .into_iter()
2084            .map(|raw| raw.cast())
2085            .collect())
2086    }
2087
2088    /// Get an event of a statically-known type from the account data store.
2089    async fn get_account_data_event_static<C>(
2090        &self,
2091    ) -> Result<Option<Raw<GlobalAccountDataEvent<C>>>, Self::Error>
2092    where
2093        C: StaticEventContent<IsPrefix = ruma::events::False> + GlobalAccountDataEventContent,
2094    {
2095        Ok(self.get_account_data_event(C::TYPE.into()).await?.map(Raw::cast_unchecked))
2096    }
2097
2098    /// Get an event of a statically-known type from the room account data
2099    /// store.
2100    ///
2101    /// # Arguments
2102    ///
2103    /// - `room_id` - The id of the room for which the room account data event
2104    ///   should be fetched.
2105    async fn get_room_account_data_event_static<C>(
2106        &self,
2107        room_id: &RoomId,
2108    ) -> Result<Option<Raw<RoomAccountDataEvent<C>>>, Self::Error>
2109    where
2110        C: StaticEventContent<IsPrefix = ruma::events::False> + RoomAccountDataEventContent,
2111    {
2112        Ok(self
2113            .get_room_account_data_event(room_id, C::TYPE.into())
2114            .await?
2115            .map(Raw::cast_unchecked))
2116    }
2117
2118    /// Get the `MemberEvent` for the given state key in the given room id.
2119    ///
2120    /// # Arguments
2121    ///
2122    /// * `room_id` - The room id the member event belongs to.
2123    ///
2124    /// * `state_key` - The user id that the member event defines the state for.
2125    async fn get_member_event(
2126        &self,
2127        room_id: &RoomId,
2128        state_key: &UserId,
2129    ) -> Result<Option<RawMemberEvent>, Self::Error> {
2130        self.get_state_event_static_for_key(room_id, state_key).await
2131    }
2132}
2133
2134#[cfg_attr(target_family = "wasm", async_trait(?Send))]
2135#[cfg_attr(not(target_family = "wasm"), async_trait)]
2136impl<T: StateStore + ?Sized> StateStoreExt for T {}
2137
2138/// A type-erased [`StateStore`].
2139pub type DynStateStore = dyn StateStore<Error = StoreError>;
2140
2141/// A type that can be type-erased into `Arc<dyn StateStore>`.
2142///
2143/// This trait is not meant to be implemented directly outside
2144/// `matrix-sdk-crypto`, but it is automatically implemented for everything that
2145/// implements `StateStore`.
2146pub trait IntoStateStore {
2147    #[doc(hidden)]
2148    fn into_state_store(self) -> Arc<DynStateStore>;
2149}
2150
2151impl<T> IntoStateStore for T
2152where
2153    T: StateStore + Sized + 'static,
2154{
2155    fn into_state_store(self) -> Arc<DynStateStore> {
2156        Arc::new(EraseStateStoreError(self))
2157    }
2158}
2159
2160/// Serialisable representation of get_supported_versions::Response.
2161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
2162pub struct SupportedVersionsResponse {
2163    /// Versions supported by the remote server.
2164    pub versions: Vec<String>,
2165
2166    /// List of unstable features and their enablement status.
2167    pub unstable_features: BTreeMap<String, bool>,
2168}
2169
2170impl SupportedVersionsResponse {
2171    /// Extracts known Matrix versions and features from the un-typed lists of
2172    /// strings.
2173    ///
2174    /// Note: Matrix versions and features that Ruma cannot parse, or does not
2175    /// know about, are discarded.
2176    pub fn supported_versions(&self) -> SupportedVersions {
2177        let mut supported_versions =
2178            SupportedVersions::from_parts(&self.versions, &self.unstable_features);
2179
2180        // We need at least one supported version to be able to make requests,
2181        // so we default to Matrix 1.0.
2182        if supported_versions.versions.is_empty() {
2183            supported_versions.versions.insert(MatrixVersion::V1_0);
2184        }
2185
2186        supported_versions
2187    }
2188}
2189
2190#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
2191/// A serialisable representation of discover_homeserver::Response.
2192pub struct WellKnownResponse {
2193    /// Information about the homeserver to connect to.
2194    pub homeserver: HomeserverInfo,
2195
2196    /// Information about the identity server to connect to.
2197    pub identity_server: Option<IdentityServerInfo>,
2198
2199    /// Information about the tile server to use to display location data.
2200    pub tile_server: Option<TileServerInfo>,
2201
2202    /// A list of the available MatrixRTC foci, ordered by priority.
2203    pub rtc_foci: Vec<RtcTransport>,
2204}
2205
2206impl From<discover_homeserver::Response> for WellKnownResponse {
2207    fn from(response: discover_homeserver::Response) -> Self {
2208        Self {
2209            homeserver: response.homeserver,
2210            identity_server: response.identity_server,
2211            tile_server: response.tile_server,
2212            rtc_foci: response.rtc_foci,
2213        }
2214    }
2215}
2216
2217/// A value for key-value data that should be persisted into the store.
2218#[derive(Debug, Clone)]
2219pub enum StateStoreDataValue {
2220    /// The sync token.
2221    SyncToken(String),
2222
2223    /// The supported versions of the server.
2224    SupportedVersions(TtlValue<SupportedVersionsResponse>),
2225
2226    /// The well-known information of the server.
2227    WellKnown(TtlValue<Option<WellKnownResponse>>),
2228
2229    /// A filter with the given ID.
2230    Filter(String),
2231
2232    /// The user avatar url
2233    UserAvatarUrl(OwnedMxcUri),
2234
2235    /// A list of recently visited room identifiers for the current user
2236    RecentlyVisitedRooms(Vec<OwnedRoomId>),
2237
2238    /// Persistent data for
2239    /// `matrix_sdk_ui::unable_to_decrypt_hook::UtdHookManager`.
2240    UtdHookManagerData(GrowableBloom),
2241
2242    /// A unit value telling us that the client uploaded duplicate one-time
2243    /// keys.
2244    OneTimeKeyAlreadyUploaded,
2245
2246    /// A composer draft for the room. To learn more, see [`ComposerDraft`].
2247    ///
2248    /// [`ComposerDraft`]: Self::ComposerDraft
2249    ComposerDraft(ComposerDraft),
2250
2251    /// A list of knock request ids marked as seen in a room.
2252    SeenKnockRequests(BTreeMap<OwnedEventId, OwnedUserId>),
2253
2254    /// A list of tokens to continue thread subscriptions catchup.
2255    ///
2256    /// See documentation of [`ThreadSubscriptionCatchupToken`] for more
2257    /// details.
2258    ThreadSubscriptionsCatchupTokens(Vec<ThreadSubscriptionCatchupToken>),
2259
2260    /// The capabilities the homeserver supports or disables.
2261    HomeserverCapabilities(TtlValue<Capabilities>),
2262}
2263
2264/// Tokens to use when catching up on thread subscriptions.
2265///
2266/// These tokens are created when the client receives some thread subscriptions
2267/// from sync, but the sync indicates that there are more thread subscriptions
2268/// available on the server. In this case, it's expected that the client will
2269/// call the [MSC4308] companion endpoint to catch up (back-paginate) on
2270/// previous thread subscriptions.
2271///
2272/// [MSC4308]: https://github.com/matrix-org/matrix-spec-proposals/pull/4308
2273#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2274pub struct ThreadSubscriptionCatchupToken {
2275    /// The token to use as the lower bound when fetching new threads
2276    /// subscriptions.
2277    ///
2278    /// In sliding sync, this is the `prev_batch` value of a sliding sync
2279    /// response.
2280    pub from: String,
2281
2282    /// The token to use as the upper bound when fetching new threads
2283    /// subscriptions.
2284    ///
2285    /// In sliding sync, it must be set to the `pos` value of the sliding sync
2286    /// _request_, which response received a `prev_batch` token.
2287    pub to: Option<String>,
2288}
2289
2290/// Current draft of the composer for the room.
2291#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2292pub struct ComposerDraft {
2293    /// The draft content in plain text.
2294    pub plain_text: String,
2295    /// If the message is formatted in HTML, the HTML representation of the
2296    /// message.
2297    pub html_text: Option<String>,
2298    /// The type of draft.
2299    pub draft_type: ComposerDraftType,
2300    /// Attachments associated with this draft.
2301    #[serde(default)]
2302    pub attachments: Vec<DraftAttachment>,
2303}
2304
2305/// An attachment stored with a composer draft.
2306#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2307pub struct DraftAttachment {
2308    /// The filename of the attachment.
2309    pub filename: String,
2310    /// The attachment content with type-specific data.
2311    pub content: DraftAttachmentContent,
2312}
2313
2314/// The content of a draft attachment with type-specific data.
2315#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2316#[serde(tag = "type")]
2317pub enum DraftAttachmentContent {
2318    /// Image attachment.
2319    Image {
2320        /// The image file data.
2321        #[serde(with = "serde_bytes")]
2322        data: Vec<u8>,
2323        /// MIME type.
2324        mimetype: Option<String>,
2325        /// File size in bytes.
2326        size: Option<u64>,
2327        /// Width in pixels.
2328        width: Option<u64>,
2329        /// Height in pixels.
2330        height: Option<u64>,
2331        /// BlurHash string.
2332        blurhash: Option<String>,
2333        /// Optional thumbnail.
2334        thumbnail: Option<DraftThumbnail>,
2335    },
2336    /// Video attachment.
2337    Video {
2338        /// The video file data.
2339        #[serde(with = "serde_bytes")]
2340        data: Vec<u8>,
2341        /// MIME type.
2342        mimetype: Option<String>,
2343        /// File size in bytes.
2344        size: Option<u64>,
2345        /// Width in pixels.
2346        width: Option<u64>,
2347        /// Height in pixels.
2348        height: Option<u64>,
2349        /// Duration.
2350        duration: Option<std::time::Duration>,
2351        /// BlurHash string.
2352        blurhash: Option<String>,
2353        /// Optional thumbnail.
2354        thumbnail: Option<DraftThumbnail>,
2355    },
2356    /// Audio attachment.
2357    Audio {
2358        /// The audio file data.
2359        #[serde(with = "serde_bytes")]
2360        data: Vec<u8>,
2361        /// MIME type.
2362        mimetype: Option<String>,
2363        /// File size in bytes.
2364        size: Option<u64>,
2365        /// Duration.
2366        duration: Option<std::time::Duration>,
2367    },
2368    /// Generic file attachment.
2369    File {
2370        /// The file data.
2371        #[serde(with = "serde_bytes")]
2372        data: Vec<u8>,
2373        /// MIME type.
2374        mimetype: Option<String>,
2375        /// File size in bytes.
2376        size: Option<u64>,
2377    },
2378}
2379
2380/// Thumbnail data for a draft attachment.
2381#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2382pub struct DraftThumbnail {
2383    /// The filename of the thumbnail.
2384    pub filename: String,
2385    /// The thumbnail image data.
2386    #[serde(with = "serde_bytes")]
2387    pub data: Vec<u8>,
2388    /// MIME type of the thumbnail.
2389    pub mimetype: Option<String>,
2390    /// Width in pixels.
2391    pub width: Option<u64>,
2392    /// Height in pixels.
2393    pub height: Option<u64>,
2394    /// File size in bytes.
2395    pub size: Option<u64>,
2396}
2397
2398/// The type of draft of the composer.
2399#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2400pub enum ComposerDraftType {
2401    /// The draft is a new message.
2402    NewMessage,
2403    /// The draft is a reply to an event.
2404    Reply {
2405        /// The ID of the event being replied to.
2406        event_id: OwnedEventId,
2407    },
2408    /// The draft is an edit of an event.
2409    Edit {
2410        /// The ID of the event being edited.
2411        event_id: OwnedEventId,
2412    },
2413}
2414
2415impl StateStoreDataValue {
2416    /// Get this value if it is a sync token.
2417    pub fn into_sync_token(self) -> Option<String> {
2418        as_variant!(self, Self::SyncToken)
2419    }
2420
2421    /// Get this value if it is a filter.
2422    pub fn into_filter(self) -> Option<String> {
2423        as_variant!(self, Self::Filter)
2424    }
2425
2426    /// Get this value if it is a user avatar url.
2427    pub fn into_user_avatar_url(self) -> Option<OwnedMxcUri> {
2428        as_variant!(self, Self::UserAvatarUrl)
2429    }
2430
2431    /// Get this value if it is a list of recently visited rooms.
2432    pub fn into_recently_visited_rooms(self) -> Option<Vec<OwnedRoomId>> {
2433        as_variant!(self, Self::RecentlyVisitedRooms)
2434    }
2435
2436    /// Get this value if it is the data for the `UtdHookManager`.
2437    pub fn into_utd_hook_manager_data(self) -> Option<GrowableBloom> {
2438        as_variant!(self, Self::UtdHookManagerData)
2439    }
2440
2441    /// Get this value if it is a composer draft.
2442    pub fn into_composer_draft(self) -> Option<ComposerDraft> {
2443        as_variant!(self, Self::ComposerDraft)
2444    }
2445
2446    /// Get this value if it is the supported versions metadata.
2447    pub fn into_supported_versions(self) -> Option<TtlValue<SupportedVersionsResponse>> {
2448        as_variant!(self, Self::SupportedVersions)
2449    }
2450
2451    /// Get this value if it is the well-known metadata.
2452    pub fn into_well_known(self) -> Option<TtlValue<Option<WellKnownResponse>>> {
2453        as_variant!(self, Self::WellKnown)
2454    }
2455
2456    /// Get this value if it is the data for the ignored join requests.
2457    pub fn into_seen_knock_requests(self) -> Option<BTreeMap<OwnedEventId, OwnedUserId>> {
2458        as_variant!(self, Self::SeenKnockRequests)
2459    }
2460
2461    /// Get this value if it is the data for the thread subscriptions catchup
2462    /// tokens.
2463    pub fn into_thread_subscriptions_catchup_tokens(
2464        self,
2465    ) -> Option<Vec<ThreadSubscriptionCatchupToken>> {
2466        as_variant!(self, Self::ThreadSubscriptionsCatchupTokens)
2467    }
2468
2469    /// Get this value if it is the data for the capabilities the homeserver
2470    /// supports or disables.
2471    pub fn into_homeserver_capabilities(self) -> Option<TtlValue<Capabilities>> {
2472        as_variant!(self, Self::HomeserverCapabilities)
2473    }
2474}
2475
2476/// A key for key-value data.
2477#[derive(Debug, Clone, Copy)]
2478pub enum StateStoreDataKey<'a> {
2479    /// The sync token.
2480    SyncToken,
2481
2482    /// The supported versions of the server,
2483    SupportedVersions,
2484
2485    /// The well-known information of the server,
2486    WellKnown,
2487
2488    /// A filter with the given name.
2489    Filter(&'a str),
2490
2491    /// Avatar URL
2492    UserAvatarUrl(&'a UserId),
2493
2494    /// Recently visited room identifiers
2495    RecentlyVisitedRooms(&'a UserId),
2496
2497    /// Persistent data for
2498    /// `matrix_sdk_ui::unable_to_decrypt_hook::UtdHookManager`.
2499    UtdHookManagerData,
2500
2501    /// Data remembering if the client already reported that it has uploaded
2502    /// duplicate one-time keys.
2503    OneTimeKeyAlreadyUploaded,
2504
2505    /// A composer draft for the room. To learn more, see [`ComposerDraft`].
2506    ///
2507    /// [`ComposerDraft`]: Self::ComposerDraft
2508    ComposerDraft(&'a RoomId, Option<&'a EventId>),
2509
2510    /// A list of knock request ids marked as seen in a room.
2511    SeenKnockRequests(&'a RoomId),
2512
2513    /// A list of thread subscriptions catchup tokens.
2514    ThreadSubscriptionsCatchupTokens,
2515
2516    /// A list of capabilities that the homeserver supports.
2517    HomeserverCapabilities,
2518}
2519
2520impl StateStoreDataKey<'_> {
2521    /// Key to use for the [`SyncToken`][Self::SyncToken] variant.
2522    pub const SYNC_TOKEN: &'static str = "sync_token";
2523
2524    /// Key to use for the [`SupportedVersions`][Self::SupportedVersions]
2525    /// variant.
2526    // Note: this is the old name, kept for backwards compatibility.
2527    pub const SUPPORTED_VERSIONS: &'static str = "server_capabilities";
2528
2529    /// Key to use for the [`WellKnown`][Self::WellKnown] variant.
2530    pub const WELL_KNOWN: &'static str = "well_known";
2531
2532    /// Key prefix to use for the [`Filter`][Self::Filter] variant.
2533    pub const FILTER: &'static str = "filter";
2534
2535    /// Key prefix to use for the [`UserAvatarUrl`][Self::UserAvatarUrl]
2536    /// variant.
2537    pub const USER_AVATAR_URL: &'static str = "user_avatar_url";
2538
2539    /// Key prefix to use for the
2540    /// [`RecentlyVisitedRooms`][Self::RecentlyVisitedRooms] variant.
2541    pub const RECENTLY_VISITED_ROOMS: &'static str = "recently_visited_rooms";
2542
2543    /// Key to use for the [`UtdHookManagerData`][Self::UtdHookManagerData]
2544    /// variant.
2545    pub const UTD_HOOK_MANAGER_DATA: &'static str = "utd_hook_manager_data";
2546
2547    /// Key to use for the flag remembering that we already reported that we
2548    /// uploaded duplicate one-time keys.
2549    pub const ONE_TIME_KEY_ALREADY_UPLOADED: &'static str = "one_time_key_already_uploaded";
2550
2551    /// Key prefix to use for the [`ComposerDraft`][Self::ComposerDraft]
2552    /// variant.
2553    pub const COMPOSER_DRAFT: &'static str = "composer_draft";
2554
2555    /// Key prefix to use for the [`SeenKnockRequests`][Self::SeenKnockRequests]
2556    /// variant.
2557    pub const SEEN_KNOCK_REQUESTS: &'static str = "seen_knock_requests";
2558
2559    /// Key prefix to use for the
2560    /// [`ThreadSubscriptionsCatchupTokens`][Self::ThreadSubscriptionsCatchupTokens]
2561    /// variant.
2562    pub const THREAD_SUBSCRIPTIONS_CATCHUP_TOKENS: &'static str =
2563        "thread_subscriptions_catchup_tokens";
2564
2565    /// Key prefix to use for the homeserver's [`Capabilities`].
2566    pub const HOMESERVER_CAPABILITIES: &'static str = "homeserver_capabilities";
2567}
2568
2569/// Compare two thread subscription changes bump stamps, given a fixed room and
2570/// thread root event id pair.
2571///
2572/// May update the newer one to keep the previous one if needed, under some
2573/// conditions.
2574///
2575/// Returns true if the new subscription should be stored, or false if the new
2576/// subscription should be ignored.
2577pub fn compare_thread_subscription_bump_stamps(
2578    previous: Option<u64>,
2579    new: &mut Option<u64>,
2580) -> bool {
2581    match (previous, &new) {
2582        // If the previous subscription had a bump stamp, and the new one
2583        // doesn't, keep the previous one; it should be updated soon via sync
2584        // anyways.
2585        (Some(prev_bump), None) => {
2586            *new = Some(prev_bump);
2587        }
2588
2589        // If the previous bump stamp is newer than the new one, don't store the value at all.
2590        (Some(prev_bump), Some(new_bump)) if *new_bump <= prev_bump => {
2591            return false;
2592        }
2593
2594        // In all other cases, keep the new bumpstamp.
2595        _ => {}
2596    }
2597
2598    true
2599}
2600
2601#[cfg(test)]
2602mod tests {
2603    mod save_locked_state_store {
2604        use std::time::Duration;
2605
2606        use assert_matches::assert_matches;
2607        use futures_util::future::{self, Either};
2608        #[cfg(all(target_family = "wasm", target_os = "unknown"))]
2609        use gloo_timers::future::sleep;
2610        use matrix_sdk_common::executor::spawn;
2611        use matrix_sdk_test::async_test;
2612        use ruma::room_id;
2613        use tokio::sync::Mutex;
2614        #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
2615        use tokio::time::sleep;
2616
2617        use crate::{
2618            StateChanges, StateStore,
2619            store::{IntoStateStore, MemoryStore, Result, SaveLockedStateStore},
2620        };
2621
2622        async fn get_store() -> Result<impl StateStore> {
2623            Ok(SaveLockedStateStore::new(MemoryStore::new()))
2624        }
2625
2626        statestore_integration_tests!();
2627
2628        #[async_test]
2629        async fn test_save_changes_only_accepts_guard_for_underlying_mutex() {
2630            let state_store = SaveLockedStateStore::new(MemoryStore::new());
2631            let state_changes = StateChanges::default();
2632            state_store
2633                .save_changes_with_guard(&state_store.lock().lock().await, &state_changes)
2634                .await
2635                .expect("state store accepts guard for underlying mutex");
2636
2637            let mutex = Mutex::new(());
2638            state_store
2639                .save_changes_with_guard(&mutex.lock().await, &state_changes)
2640                .await
2641                .expect_err("state store does not accept guard for unknown mutex");
2642        }
2643
2644        #[async_test]
2645        async fn test_remove_room_only_accepts_guard_for_underlying_mutex() {
2646            let state_store = SaveLockedStateStore::new(MemoryStore::new());
2647            let room_id = room_id!("!room");
2648            state_store
2649                .remove_room_with_guard(&state_store.lock().lock().await, room_id)
2650                .await
2651                .expect("state store accepts guard for underlying mutex");
2652
2653            let mutex = Mutex::new(());
2654            state_store
2655                .remove_room_with_guard(&mutex.lock().await, room_id)
2656                .await
2657                .expect_err("state store does not accept guard for unknown mutex");
2658        }
2659
2660        #[derive(Debug)]
2661        struct Elapsed;
2662
2663        async fn timeout<F: Future + Unpin>(
2664            duration: Duration,
2665            f: F,
2666        ) -> Result<F::Output, Elapsed> {
2667            #[cfg(all(target_family = "wasm", target_os = "unknown"))]
2668            {
2669                match future::select(sleep(duration), f).await {
2670                    Either::Left(_) => return Err(Elapsed),
2671                    Either::Right((output, _)) => Ok(output),
2672                }
2673            }
2674            #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
2675            {
2676                tokio::time::timeout(duration, f).await.map_err(|_| Elapsed)
2677            }
2678        }
2679
2680        #[async_test]
2681        async fn test_state_store_waits_to_acquire_lock_before_saving_changes() {
2682            let state_store = SaveLockedStateStore::new(MemoryStore::new().into_state_store());
2683
2684            // Acquire lock and hold it for 5 seconds
2685            let lock_task = spawn({
2686                let state_store = state_store.clone();
2687                async move {
2688                    let lock = state_store.lock();
2689                    let _guard = lock.lock().await;
2690                    sleep(Duration::from_secs(5)).await;
2691                }
2692            });
2693
2694            // Try to save changes to the state store while the lock is held by
2695            // another task
2696            let save_task =
2697                spawn(async move { state_store.save_changes(&StateChanges::default()).await });
2698
2699            // Ensure that the second task does not progress until the first
2700            // task has completed and therefore release the save lock
2701            assert_matches!(future::select(lock_task, save_task).await, Either::Left((_, save_task)) => {
2702                timeout(Duration::from_millis(100), save_task)
2703                    .await
2704                    .expect("task completes before timeout")
2705                    .expect("task completes successfully")
2706                    .expect("task saves changes");
2707            });
2708        }
2709
2710        #[async_test]
2711        async fn test_state_store_waits_to_acquire_lock_before_removing_room() {
2712            let state_store = SaveLockedStateStore::new(MemoryStore::new().into_state_store());
2713
2714            // Acquire lock and hold it for 5 seconds
2715            let lock_task = spawn({
2716                let state_store = state_store.clone();
2717                async move {
2718                    let lock = state_store.lock();
2719                    let _guard = lock.lock().await;
2720                    sleep(Duration::from_secs(5)).await;
2721                }
2722            });
2723
2724            // Try to remove room from the state store while the lock is held by
2725            // another task
2726            let remove_task =
2727                spawn(async move { state_store.remove_room(room_id!("!room")).await });
2728
2729            // Ensure that the second task does not progress until the first
2730            // task has completed and therefore release the save lock
2731            assert_matches!(future::select(lock_task, remove_task).await, Either::Left((_, remove_task)) => {
2732                timeout(Duration::from_millis(100), remove_task)
2733                    .await
2734                    .expect("task completes before timeout")
2735                    .expect("task completes successfully")
2736                    .expect("task saves changes");
2737            });
2738        }
2739    }
2740}