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    /// Close the store, releasing all held resources (database connections,
535    /// file descriptors, file locks).
536    ///
537    /// In-flight operations complete before this method returns. After it
538    /// returns, operations will fail until [`Self::reopen()`] is called.
539    async fn close(&self) -> Result<(), Self::Error>;
540
541    /// Reopen the store after a [`Self::close()`], re-acquiring database
542    /// connections.
543    async fn reopen(&self) -> Result<(), Self::Error>;
544
545    /// Perform database optimizations if any are available, i.e. vacuuming in
546    /// SQLite.
547    ///
548    /// /// **Warning:** this was added to check if SQLite fragmentation was the
549    /// source of performance issues, **DO NOT use in production**.
550    #[doc(hidden)]
551    async fn optimize(&self) -> Result<(), Self::Error>;
552
553    /// Returns the size of the store in bytes, if known.
554    async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
555}
556
557#[cfg_attr(target_family = "wasm", async_trait(?Send))]
558#[cfg_attr(not(target_family = "wasm"), async_trait)]
559impl<T: StateStore> StateStore for &T {
560    type Error = T::Error;
561
562    async fn get_kv_data(
563        &self,
564        key: StateStoreDataKey<'_>,
565    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
566        (*self).get_kv_data(key).await
567    }
568
569    async fn set_kv_data(
570        &self,
571        key: StateStoreDataKey<'_>,
572        value: StateStoreDataValue,
573    ) -> Result<(), Self::Error> {
574        (*self).set_kv_data(key, value).await
575    }
576
577    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
578        (*self).remove_kv_data(key).await
579    }
580
581    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
582        (*self).save_changes(changes).await
583    }
584
585    async fn get_presence_event(
586        &self,
587        user_id: &UserId,
588    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
589        (*self).get_presence_event(user_id).await
590    }
591
592    async fn get_presence_events(
593        &self,
594        user_ids: &[OwnedUserId],
595    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
596        (*self).get_presence_events(user_ids).await
597    }
598
599    async fn get_state_event(
600        &self,
601        room_id: &RoomId,
602        event_type: StateEventType,
603        state_key: &str,
604    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
605        (*self).get_state_event(room_id, event_type, state_key).await
606    }
607
608    async fn get_state_events(
609        &self,
610        room_id: &RoomId,
611        event_type: StateEventType,
612    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
613        (*self).get_state_events(room_id, event_type).await
614    }
615
616    async fn get_state_events_for_keys(
617        &self,
618        room_id: &RoomId,
619        event_type: StateEventType,
620        state_keys: &[&str],
621    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
622        (*self).get_state_events_for_keys(room_id, event_type, state_keys).await
623    }
624
625    async fn get_profile(
626        &self,
627        room_id: &RoomId,
628        user_id: &UserId,
629    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
630        (*self).get_profile(room_id, user_id).await
631    }
632
633    async fn get_profiles<'a>(
634        &self,
635        room_id: &RoomId,
636        user_ids: &'a [OwnedUserId],
637    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
638        (*self).get_profiles(room_id, user_ids).await
639    }
640
641    async fn get_user_ids(
642        &self,
643        room_id: &RoomId,
644        memberships: RoomMemberships,
645    ) -> Result<Vec<OwnedUserId>, Self::Error> {
646        (*self).get_user_ids(room_id, memberships).await
647    }
648
649    async fn get_room_infos(
650        &self,
651        room_load_settings: &RoomLoadSettings,
652    ) -> Result<Vec<RoomInfo>, Self::Error> {
653        (*self).get_room_infos(room_load_settings).await
654    }
655
656    async fn get_users_with_display_name(
657        &self,
658        room_id: &RoomId,
659        display_name: &DisplayName,
660    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
661        (*self).get_users_with_display_name(room_id, display_name).await
662    }
663
664    async fn get_users_with_display_names<'a>(
665        &self,
666        room_id: &RoomId,
667        display_names: &'a [DisplayName],
668    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
669        (*self).get_users_with_display_names(room_id, display_names).await
670    }
671
672    async fn get_account_data_event(
673        &self,
674        event_type: GlobalAccountDataEventType,
675    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
676        (*self).get_account_data_event(event_type).await
677    }
678
679    async fn get_room_account_data_event(
680        &self,
681        room_id: &RoomId,
682        event_type: RoomAccountDataEventType,
683    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
684        (*self).get_room_account_data_event(room_id, event_type).await
685    }
686
687    async fn get_user_room_receipt_event(
688        &self,
689        room_id: &RoomId,
690        receipt_type: ReceiptType,
691        receipt_thread: &ReceiptThread,
692        user_id: &UserId,
693    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
694        (*self).get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id).await
695    }
696
697    async fn get_event_room_receipt_events(
698        &self,
699        room_id: &RoomId,
700        receipt_type: ReceiptType,
701        receipt_thread: &ReceiptThread,
702        event_id: &EventId,
703    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
704        (*self).get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id).await
705    }
706
707    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
708        (*self).get_custom_value(key).await
709    }
710
711    async fn set_custom_value(
712        &self,
713        key: &[u8],
714        value: Vec<u8>,
715    ) -> Result<Option<Vec<u8>>, Self::Error> {
716        (*self).set_custom_value(key, value).await
717    }
718
719    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
720        (*self).remove_custom_value(key).await
721    }
722
723    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
724        (*self).remove_room(room_id).await
725    }
726
727    async fn save_send_queue_request(
728        &self,
729        room_id: &RoomId,
730        transaction_id: OwnedTransactionId,
731        created_at: MilliSecondsSinceUnixEpoch,
732        request: QueuedRequestKind,
733        priority: usize,
734    ) -> Result<(), Self::Error> {
735        (*self)
736            .save_send_queue_request(room_id, transaction_id, created_at, request, priority)
737            .await
738    }
739
740    async fn update_send_queue_request(
741        &self,
742        room_id: &RoomId,
743        transaction_id: &TransactionId,
744        content: QueuedRequestKind,
745    ) -> Result<bool, Self::Error> {
746        (*self).update_send_queue_request(room_id, transaction_id, content).await
747    }
748
749    async fn remove_send_queue_request(
750        &self,
751        room_id: &RoomId,
752        transaction_id: &TransactionId,
753    ) -> Result<bool, Self::Error> {
754        (*self).remove_send_queue_request(room_id, transaction_id).await
755    }
756
757    async fn load_send_queue_requests(
758        &self,
759        room_id: &RoomId,
760    ) -> Result<Vec<QueuedRequest>, Self::Error> {
761        (*self).load_send_queue_requests(room_id).await
762    }
763
764    async fn update_send_queue_request_status(
765        &self,
766        room_id: &RoomId,
767        transaction_id: &TransactionId,
768        error: Option<QueueWedgeError>,
769    ) -> Result<(), Self::Error> {
770        (*self).update_send_queue_request_status(room_id, transaction_id, error).await
771    }
772
773    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
774        (*self).load_rooms_with_unsent_requests().await
775    }
776
777    async fn save_dependent_queued_request(
778        &self,
779        room_id: &RoomId,
780        parent_txn_id: &TransactionId,
781        own_txn_id: ChildTransactionId,
782        created_at: MilliSecondsSinceUnixEpoch,
783        content: DependentQueuedRequestKind,
784    ) -> Result<(), Self::Error> {
785        (*self)
786            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
787            .await
788    }
789
790    async fn mark_dependent_queued_requests_as_ready(
791        &self,
792        room_id: &RoomId,
793        parent_txn_id: &TransactionId,
794        sent_parent_key: SentRequestKey,
795    ) -> Result<usize, Self::Error> {
796        (*self)
797            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
798            .await
799    }
800
801    async fn update_dependent_queued_request(
802        &self,
803        room_id: &RoomId,
804        own_transaction_id: &ChildTransactionId,
805        new_content: DependentQueuedRequestKind,
806    ) -> Result<bool, Self::Error> {
807        (*self).update_dependent_queued_request(room_id, own_transaction_id, new_content).await
808    }
809
810    async fn remove_dependent_queued_request(
811        &self,
812        room: &RoomId,
813        own_txn_id: &ChildTransactionId,
814    ) -> Result<bool, Self::Error> {
815        (*self).remove_dependent_queued_request(room, own_txn_id).await
816    }
817
818    async fn load_dependent_queued_requests(
819        &self,
820        room: &RoomId,
821    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
822        (*self).load_dependent_queued_requests(room).await
823    }
824
825    async fn upsert_thread_subscriptions(
826        &self,
827        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
828    ) -> Result<(), Self::Error> {
829        (*self).upsert_thread_subscriptions(updates).await
830    }
831
832    async fn remove_thread_subscription(
833        &self,
834        room: &RoomId,
835        thread_id: &EventId,
836    ) -> Result<(), Self::Error> {
837        (*self).remove_thread_subscription(room, thread_id).await
838    }
839
840    async fn load_thread_subscription(
841        &self,
842        room: &RoomId,
843        thread_id: &EventId,
844    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
845        (*self).load_thread_subscription(room, thread_id).await
846    }
847
848    async fn get_global_profile(
849        &self,
850        user_id: &UserId,
851    ) -> Result<Option<UserProfile>, Self::Error> {
852        (*self).get_global_profile(user_id).await
853    }
854
855    async fn get_global_profiles<'a>(
856        &self,
857        user_ids: &'a [OwnedUserId],
858    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
859        (*self).get_global_profiles(user_ids).await
860    }
861
862    async fn close(&self) -> Result<(), Self::Error> {
863        (*self).close().await
864    }
865
866    async fn reopen(&self) -> Result<(), Self::Error> {
867        (*self).reopen().await
868    }
869
870    async fn optimize(&self) -> Result<(), Self::Error> {
871        (*self).optimize().await
872    }
873
874    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
875        (*self).get_size().await
876    }
877}
878
879#[cfg_attr(target_family = "wasm", async_trait(?Send))]
880#[cfg_attr(not(target_family = "wasm"), async_trait)]
881impl<T: StateStore + ?Sized> StateStore for Arc<T> {
882    type Error = T::Error;
883
884    async fn get_kv_data(
885        &self,
886        key: StateStoreDataKey<'_>,
887    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
888        self.deref().get_kv_data(key).await
889    }
890
891    async fn set_kv_data(
892        &self,
893        key: StateStoreDataKey<'_>,
894        value: StateStoreDataValue,
895    ) -> Result<(), Self::Error> {
896        self.deref().set_kv_data(key, value).await
897    }
898
899    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
900        self.deref().remove_kv_data(key).await
901    }
902
903    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
904        self.deref().save_changes(changes).await
905    }
906
907    async fn get_presence_event(
908        &self,
909        user_id: &UserId,
910    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
911        self.deref().get_presence_event(user_id).await
912    }
913
914    async fn get_presence_events(
915        &self,
916        user_ids: &[OwnedUserId],
917    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
918        self.deref().get_presence_events(user_ids).await
919    }
920
921    async fn get_state_event(
922        &self,
923        room_id: &RoomId,
924        event_type: StateEventType,
925        state_key: &str,
926    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
927        self.deref().get_state_event(room_id, event_type, state_key).await
928    }
929
930    async fn get_state_events(
931        &self,
932        room_id: &RoomId,
933        event_type: StateEventType,
934    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
935        self.deref().get_state_events(room_id, event_type).await
936    }
937
938    async fn get_state_events_for_keys(
939        &self,
940        room_id: &RoomId,
941        event_type: StateEventType,
942        state_keys: &[&str],
943    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
944        self.deref().get_state_events_for_keys(room_id, event_type, state_keys).await
945    }
946
947    async fn get_profile(
948        &self,
949        room_id: &RoomId,
950        user_id: &UserId,
951    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
952        self.deref().get_profile(room_id, user_id).await
953    }
954
955    async fn get_profiles<'a>(
956        &self,
957        room_id: &RoomId,
958        user_ids: &'a [OwnedUserId],
959    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
960        self.deref().get_profiles(room_id, user_ids).await
961    }
962
963    async fn get_user_ids(
964        &self,
965        room_id: &RoomId,
966        memberships: RoomMemberships,
967    ) -> Result<Vec<OwnedUserId>, Self::Error> {
968        self.deref().get_user_ids(room_id, memberships).await
969    }
970
971    async fn get_room_infos(
972        &self,
973        room_load_settings: &RoomLoadSettings,
974    ) -> Result<Vec<RoomInfo>, Self::Error> {
975        self.deref().get_room_infos(room_load_settings).await
976    }
977
978    async fn get_users_with_display_name(
979        &self,
980        room_id: &RoomId,
981        display_name: &DisplayName,
982    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
983        self.deref().get_users_with_display_name(room_id, display_name).await
984    }
985
986    async fn get_users_with_display_names<'a>(
987        &self,
988        room_id: &RoomId,
989        display_names: &'a [DisplayName],
990    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
991        self.deref().get_users_with_display_names(room_id, display_names).await
992    }
993
994    async fn get_account_data_event(
995        &self,
996        event_type: GlobalAccountDataEventType,
997    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
998        self.deref().get_account_data_event(event_type).await
999    }
1000
1001    async fn get_room_account_data_event(
1002        &self,
1003        room_id: &RoomId,
1004        event_type: RoomAccountDataEventType,
1005    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
1006        self.deref().get_room_account_data_event(room_id, event_type).await
1007    }
1008
1009    async fn get_user_room_receipt_event(
1010        &self,
1011        room_id: &RoomId,
1012        receipt_type: ReceiptType,
1013        receipt_thread: &ReceiptThread,
1014        user_id: &UserId,
1015    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
1016        self.deref()
1017            .get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id)
1018            .await
1019    }
1020
1021    async fn get_event_room_receipt_events(
1022        &self,
1023        room_id: &RoomId,
1024        receipt_type: ReceiptType,
1025        receipt_thread: &ReceiptThread,
1026        event_id: &EventId,
1027    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
1028        self.deref()
1029            .get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id)
1030            .await
1031    }
1032
1033    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1034        self.deref().get_custom_value(key).await
1035    }
1036
1037    async fn set_custom_value(
1038        &self,
1039        key: &[u8],
1040        value: Vec<u8>,
1041    ) -> Result<Option<Vec<u8>>, Self::Error> {
1042        self.deref().set_custom_value(key, value).await
1043    }
1044
1045    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1046        self.deref().remove_custom_value(key).await
1047    }
1048
1049    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
1050        self.deref().remove_room(room_id).await
1051    }
1052
1053    async fn save_send_queue_request(
1054        &self,
1055        room_id: &RoomId,
1056        transaction_id: OwnedTransactionId,
1057        created_at: MilliSecondsSinceUnixEpoch,
1058        request: QueuedRequestKind,
1059        priority: usize,
1060    ) -> Result<(), Self::Error> {
1061        self.deref()
1062            .save_send_queue_request(room_id, transaction_id, created_at, request, priority)
1063            .await
1064    }
1065
1066    async fn update_send_queue_request(
1067        &self,
1068        room_id: &RoomId,
1069        transaction_id: &TransactionId,
1070        content: QueuedRequestKind,
1071    ) -> Result<bool, Self::Error> {
1072        self.deref().update_send_queue_request(room_id, transaction_id, content).await
1073    }
1074
1075    async fn remove_send_queue_request(
1076        &self,
1077        room_id: &RoomId,
1078        transaction_id: &TransactionId,
1079    ) -> Result<bool, Self::Error> {
1080        self.deref().remove_send_queue_request(room_id, transaction_id).await
1081    }
1082
1083    async fn load_send_queue_requests(
1084        &self,
1085        room_id: &RoomId,
1086    ) -> Result<Vec<QueuedRequest>, Self::Error> {
1087        self.deref().load_send_queue_requests(room_id).await
1088    }
1089
1090    async fn update_send_queue_request_status(
1091        &self,
1092        room_id: &RoomId,
1093        transaction_id: &TransactionId,
1094        error: Option<QueueWedgeError>,
1095    ) -> Result<(), Self::Error> {
1096        self.deref().update_send_queue_request_status(room_id, transaction_id, error).await
1097    }
1098
1099    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
1100        self.deref().load_rooms_with_unsent_requests().await
1101    }
1102
1103    async fn save_dependent_queued_request(
1104        &self,
1105        room_id: &RoomId,
1106        parent_txn_id: &TransactionId,
1107        own_txn_id: ChildTransactionId,
1108        created_at: MilliSecondsSinceUnixEpoch,
1109        content: DependentQueuedRequestKind,
1110    ) -> Result<(), Self::Error> {
1111        self.deref()
1112            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
1113            .await
1114    }
1115
1116    async fn mark_dependent_queued_requests_as_ready(
1117        &self,
1118        room_id: &RoomId,
1119        parent_txn_id: &TransactionId,
1120        sent_parent_key: SentRequestKey,
1121    ) -> Result<usize, Self::Error> {
1122        self.deref()
1123            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
1124            .await
1125    }
1126
1127    async fn update_dependent_queued_request(
1128        &self,
1129        room_id: &RoomId,
1130        own_transaction_id: &ChildTransactionId,
1131        new_content: DependentQueuedRequestKind,
1132    ) -> Result<bool, Self::Error> {
1133        self.deref().update_dependent_queued_request(room_id, own_transaction_id, new_content).await
1134    }
1135
1136    async fn remove_dependent_queued_request(
1137        &self,
1138        room: &RoomId,
1139        own_txn_id: &ChildTransactionId,
1140    ) -> Result<bool, Self::Error> {
1141        self.deref().remove_dependent_queued_request(room, own_txn_id).await
1142    }
1143
1144    async fn load_dependent_queued_requests(
1145        &self,
1146        room: &RoomId,
1147    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
1148        self.deref().load_dependent_queued_requests(room).await
1149    }
1150
1151    async fn upsert_thread_subscriptions(
1152        &self,
1153        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
1154    ) -> Result<(), Self::Error> {
1155        self.deref().upsert_thread_subscriptions(updates).await
1156    }
1157
1158    async fn remove_thread_subscription(
1159        &self,
1160        room: &RoomId,
1161        thread_id: &EventId,
1162    ) -> Result<(), Self::Error> {
1163        self.deref().remove_thread_subscription(room, thread_id).await
1164    }
1165
1166    async fn load_thread_subscription(
1167        &self,
1168        room: &RoomId,
1169        thread_id: &EventId,
1170    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
1171        self.deref().load_thread_subscription(room, thread_id).await
1172    }
1173
1174    async fn get_global_profile(
1175        &self,
1176        user_id: &UserId,
1177    ) -> Result<Option<UserProfile>, Self::Error> {
1178        self.deref().get_global_profile(user_id).await
1179    }
1180
1181    async fn get_global_profiles<'a>(
1182        &self,
1183        user_ids: &'a [OwnedUserId],
1184    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
1185        self.deref().get_global_profiles(user_ids).await
1186    }
1187
1188    async fn close(&self) -> Result<(), Self::Error> {
1189        self.deref().close().await
1190    }
1191
1192    async fn reopen(&self) -> Result<(), Self::Error> {
1193        self.deref().reopen().await
1194    }
1195
1196    async fn optimize(&self) -> Result<(), Self::Error> {
1197        self.deref().optimize().await
1198    }
1199
1200    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
1201        self.deref().get_size().await
1202    }
1203}
1204
1205#[repr(transparent)]
1206struct EraseStateStoreError<T>(T);
1207
1208#[cfg(not(tarpaulin_include))]
1209impl<T: fmt::Debug> fmt::Debug for EraseStateStoreError<T> {
1210    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1211        self.0.fmt(f)
1212    }
1213}
1214
1215#[cfg_attr(target_family = "wasm", async_trait(?Send))]
1216#[cfg_attr(not(target_family = "wasm"), async_trait)]
1217impl<T: StateStore> StateStore for EraseStateStoreError<T> {
1218    type Error = StoreError;
1219
1220    async fn get_kv_data(
1221        &self,
1222        key: StateStoreDataKey<'_>,
1223    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
1224        self.0.get_kv_data(key).await.map_err(Into::into)
1225    }
1226
1227    async fn set_kv_data(
1228        &self,
1229        key: StateStoreDataKey<'_>,
1230        value: StateStoreDataValue,
1231    ) -> Result<(), Self::Error> {
1232        self.0.set_kv_data(key, value).await.map_err(Into::into)
1233    }
1234
1235    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
1236        self.0.remove_kv_data(key).await.map_err(Into::into)
1237    }
1238
1239    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
1240        self.0.save_changes(changes).await.map_err(Into::into)
1241    }
1242
1243    async fn get_presence_event(
1244        &self,
1245        user_id: &UserId,
1246    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
1247        self.0.get_presence_event(user_id).await.map_err(Into::into)
1248    }
1249
1250    async fn get_presence_events(
1251        &self,
1252        user_ids: &[OwnedUserId],
1253    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
1254        self.0.get_presence_events(user_ids).await.map_err(Into::into)
1255    }
1256
1257    async fn get_state_event(
1258        &self,
1259        room_id: &RoomId,
1260        event_type: StateEventType,
1261        state_key: &str,
1262    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
1263        self.0.get_state_event(room_id, event_type, state_key).await.map_err(Into::into)
1264    }
1265
1266    async fn get_state_events(
1267        &self,
1268        room_id: &RoomId,
1269        event_type: StateEventType,
1270    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1271        self.0.get_state_events(room_id, event_type).await.map_err(Into::into)
1272    }
1273
1274    async fn get_state_events_for_keys(
1275        &self,
1276        room_id: &RoomId,
1277        event_type: StateEventType,
1278        state_keys: &[&str],
1279    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1280        self.0.get_state_events_for_keys(room_id, event_type, state_keys).await.map_err(Into::into)
1281    }
1282
1283    async fn get_profile(
1284        &self,
1285        room_id: &RoomId,
1286        user_id: &UserId,
1287    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
1288        self.0.get_profile(room_id, user_id).await.map_err(Into::into)
1289    }
1290
1291    async fn get_profiles<'a>(
1292        &self,
1293        room_id: &RoomId,
1294        user_ids: &'a [OwnedUserId],
1295    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
1296        self.0.get_profiles(room_id, user_ids).await.map_err(Into::into)
1297    }
1298
1299    async fn get_user_ids(
1300        &self,
1301        room_id: &RoomId,
1302        memberships: RoomMemberships,
1303    ) -> Result<Vec<OwnedUserId>, Self::Error> {
1304        self.0.get_user_ids(room_id, memberships).await.map_err(Into::into)
1305    }
1306
1307    async fn get_room_infos(
1308        &self,
1309        room_load_settings: &RoomLoadSettings,
1310    ) -> Result<Vec<RoomInfo>, Self::Error> {
1311        self.0.get_room_infos(room_load_settings).await.map_err(Into::into)
1312    }
1313
1314    async fn get_users_with_display_name(
1315        &self,
1316        room_id: &RoomId,
1317        display_name: &DisplayName,
1318    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
1319        self.0.get_users_with_display_name(room_id, display_name).await.map_err(Into::into)
1320    }
1321
1322    async fn get_users_with_display_names<'a>(
1323        &self,
1324        room_id: &RoomId,
1325        display_names: &'a [DisplayName],
1326    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
1327        self.0.get_users_with_display_names(room_id, display_names).await.map_err(Into::into)
1328    }
1329
1330    async fn get_account_data_event(
1331        &self,
1332        event_type: GlobalAccountDataEventType,
1333    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
1334        self.0.get_account_data_event(event_type).await.map_err(Into::into)
1335    }
1336
1337    async fn get_room_account_data_event(
1338        &self,
1339        room_id: &RoomId,
1340        event_type: RoomAccountDataEventType,
1341    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
1342        self.0.get_room_account_data_event(room_id, event_type).await.map_err(Into::into)
1343    }
1344
1345    async fn get_user_room_receipt_event(
1346        &self,
1347        room_id: &RoomId,
1348        receipt_type: ReceiptType,
1349        receipt_thread: &ReceiptThread,
1350        user_id: &UserId,
1351    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
1352        self.0
1353            .get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id)
1354            .await
1355            .map_err(Into::into)
1356    }
1357
1358    async fn get_event_room_receipt_events(
1359        &self,
1360        room_id: &RoomId,
1361        receipt_type: ReceiptType,
1362        receipt_thread: &ReceiptThread,
1363        event_id: &EventId,
1364    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
1365        self.0
1366            .get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id)
1367            .await
1368            .map_err(Into::into)
1369    }
1370
1371    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1372        self.0.get_custom_value(key).await.map_err(Into::into)
1373    }
1374
1375    async fn set_custom_value(
1376        &self,
1377        key: &[u8],
1378        value: Vec<u8>,
1379    ) -> Result<Option<Vec<u8>>, Self::Error> {
1380        self.0.set_custom_value(key, value).await.map_err(Into::into)
1381    }
1382
1383    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1384        self.0.remove_custom_value(key).await.map_err(Into::into)
1385    }
1386
1387    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
1388        self.0.remove_room(room_id).await.map_err(Into::into)
1389    }
1390
1391    async fn save_send_queue_request(
1392        &self,
1393        room_id: &RoomId,
1394        transaction_id: OwnedTransactionId,
1395        created_at: MilliSecondsSinceUnixEpoch,
1396        content: QueuedRequestKind,
1397        priority: usize,
1398    ) -> Result<(), Self::Error> {
1399        self.0
1400            .save_send_queue_request(room_id, transaction_id, created_at, content, priority)
1401            .await
1402            .map_err(Into::into)
1403    }
1404
1405    async fn update_send_queue_request(
1406        &self,
1407        room_id: &RoomId,
1408        transaction_id: &TransactionId,
1409        content: QueuedRequestKind,
1410    ) -> Result<bool, Self::Error> {
1411        self.0.update_send_queue_request(room_id, transaction_id, content).await.map_err(Into::into)
1412    }
1413
1414    async fn remove_send_queue_request(
1415        &self,
1416        room_id: &RoomId,
1417        transaction_id: &TransactionId,
1418    ) -> Result<bool, Self::Error> {
1419        self.0.remove_send_queue_request(room_id, transaction_id).await.map_err(Into::into)
1420    }
1421
1422    async fn load_send_queue_requests(
1423        &self,
1424        room_id: &RoomId,
1425    ) -> Result<Vec<QueuedRequest>, Self::Error> {
1426        self.0.load_send_queue_requests(room_id).await.map_err(Into::into)
1427    }
1428
1429    async fn update_send_queue_request_status(
1430        &self,
1431        room_id: &RoomId,
1432        transaction_id: &TransactionId,
1433        error: Option<QueueWedgeError>,
1434    ) -> Result<(), Self::Error> {
1435        self.0
1436            .update_send_queue_request_status(room_id, transaction_id, error)
1437            .await
1438            .map_err(Into::into)
1439    }
1440
1441    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
1442        self.0.load_rooms_with_unsent_requests().await.map_err(Into::into)
1443    }
1444
1445    async fn save_dependent_queued_request(
1446        &self,
1447        room_id: &RoomId,
1448        parent_txn_id: &TransactionId,
1449        own_txn_id: ChildTransactionId,
1450        created_at: MilliSecondsSinceUnixEpoch,
1451        content: DependentQueuedRequestKind,
1452    ) -> Result<(), Self::Error> {
1453        self.0
1454            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
1455            .await
1456            .map_err(Into::into)
1457    }
1458
1459    async fn mark_dependent_queued_requests_as_ready(
1460        &self,
1461        room_id: &RoomId,
1462        parent_txn_id: &TransactionId,
1463        sent_parent_key: SentRequestKey,
1464    ) -> Result<usize, Self::Error> {
1465        self.0
1466            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
1467            .await
1468            .map_err(Into::into)
1469    }
1470
1471    async fn remove_dependent_queued_request(
1472        &self,
1473        room_id: &RoomId,
1474        own_txn_id: &ChildTransactionId,
1475    ) -> Result<bool, Self::Error> {
1476        self.0.remove_dependent_queued_request(room_id, own_txn_id).await.map_err(Into::into)
1477    }
1478
1479    async fn load_dependent_queued_requests(
1480        &self,
1481        room_id: &RoomId,
1482    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
1483        self.0.load_dependent_queued_requests(room_id).await.map_err(Into::into)
1484    }
1485
1486    async fn update_dependent_queued_request(
1487        &self,
1488        room_id: &RoomId,
1489        own_transaction_id: &ChildTransactionId,
1490        new_content: DependentQueuedRequestKind,
1491    ) -> Result<bool, Self::Error> {
1492        self.0
1493            .update_dependent_queued_request(room_id, own_transaction_id, new_content)
1494            .await
1495            .map_err(Into::into)
1496    }
1497
1498    async fn upsert_thread_subscriptions(
1499        &self,
1500        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
1501    ) -> Result<(), Self::Error> {
1502        self.0.upsert_thread_subscriptions(updates).await.map_err(Into::into)
1503    }
1504
1505    async fn load_thread_subscription(
1506        &self,
1507        room: &RoomId,
1508        thread_id: &EventId,
1509    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
1510        self.0.load_thread_subscription(room, thread_id).await.map_err(Into::into)
1511    }
1512
1513    async fn remove_thread_subscription(
1514        &self,
1515        room: &RoomId,
1516        thread_id: &EventId,
1517    ) -> Result<(), Self::Error> {
1518        self.0.remove_thread_subscription(room, thread_id).await.map_err(Into::into)
1519    }
1520
1521    async fn get_global_profile(
1522        &self,
1523        user_id: &UserId,
1524    ) -> Result<Option<UserProfile>, Self::Error> {
1525        self.0.get_global_profile(user_id).await.map_err(Into::into)
1526    }
1527
1528    async fn get_global_profiles<'a>(
1529        &self,
1530        user_ids: &'a [OwnedUserId],
1531    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
1532        self.0.get_global_profiles(user_ids).await.map_err(Into::into)
1533    }
1534
1535    async fn close(&self) -> Result<(), Self::Error> {
1536        self.0.close().await.map_err(Into::into)
1537    }
1538
1539    async fn reopen(&self) -> Result<(), Self::Error> {
1540        self.0.reopen().await.map_err(Into::into)
1541    }
1542
1543    async fn optimize(&self) -> Result<(), Self::Error> {
1544        self.0.optimize().await.map_err(Into::into)
1545    }
1546
1547    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
1548        self.0.get_size().await.map_err(Into::into)
1549    }
1550}
1551
1552/// A wrapper around a [`StateStore`] that supports synchronizing calls to
1553/// [`StateStore::save_changes`].
1554#[derive(Debug, Clone)]
1555pub struct SaveLockedStateStore<T = Arc<DynStateStore>> {
1556    store: T,
1557    lock: Arc<Mutex<()>>,
1558}
1559
1560/// An error type that represents a scenario where a [`MutexGuard`] provided to
1561/// a function does not reference the underlying [`Mutex`] in the enclosing
1562/// [`SaveLockedStateStore`].
1563#[derive(Debug, Error)]
1564#[error("a mutex guard was provided, but it does not reference the correct mutex")]
1565pub struct IncorrectMutexGuardError;
1566
1567impl From<IncorrectMutexGuardError> for StoreError {
1568    fn from(value: IncorrectMutexGuardError) -> Self {
1569        Self::backend(value)
1570    }
1571}
1572
1573impl<T> SaveLockedStateStore<T> {
1574    /// Creates a new [`SaveLockedStateStore`] with the provided store.
1575    pub fn new(store: T) -> Self {
1576        Self { store, lock: Arc::new(Mutex::new(())) }
1577    }
1578
1579    /// Returns a reference to the underlying [`Mutex`] used to synchronize
1580    /// calls to [`StateStore::save_changes`].
1581    pub fn lock(&self) -> &Mutex<()> {
1582        self.lock.as_ref()
1583    }
1584}
1585
1586impl<T: StateStore> SaveLockedStateStore<T> {
1587    /// Provides a means of calling [`StateStore::save_changes`] when the caller
1588    /// has already acquired the underlying [`Mutex`]. Returns an error if the
1589    /// [`MutexGuard`] provided does not reference the underlying [`Mutex`].
1590    pub async fn save_changes_with_guard(
1591        &self,
1592        guard: &MutexGuard<'_, ()>,
1593        changes: &StateChanges,
1594    ) -> Result<(), StoreError> {
1595        if !std::ptr::eq(MutexGuard::mutex(guard), self.lock()) {
1596            Err(IncorrectMutexGuardError.into())
1597        } else {
1598            self.store.save_changes(changes).await.map_err(Into::into)
1599        }
1600    }
1601
1602    /// Provides a means of calling [`StateStore::remove_room`] when the caller
1603    /// has already acquired the underlying [`Mutex`]. Returns an error if the
1604    /// [`MutexGuard`] provided does not reference the underlying [`Mutex`].
1605    pub async fn remove_room_with_guard(
1606        &self,
1607        guard: &MutexGuard<'_, ()>,
1608        room_id: &RoomId,
1609    ) -> Result<(), StoreError> {
1610        if !std::ptr::eq(MutexGuard::mutex(guard), self.lock()) {
1611            Err(IncorrectMutexGuardError.into())
1612        } else {
1613            self.store.remove_room(room_id).await.map_err(Into::into)
1614        }
1615    }
1616}
1617
1618#[cfg_attr(target_family = "wasm", async_trait(?Send))]
1619#[cfg_attr(not(target_family = "wasm"), async_trait)]
1620impl<T: StateStore> StateStore for SaveLockedStateStore<T> {
1621    type Error = T::Error;
1622
1623    async fn get_kv_data(
1624        &self,
1625        key: StateStoreDataKey<'_>,
1626    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
1627        self.store.get_kv_data(key).await
1628    }
1629
1630    async fn set_kv_data(
1631        &self,
1632        key: StateStoreDataKey<'_>,
1633        value: StateStoreDataValue,
1634    ) -> Result<(), Self::Error> {
1635        self.store.set_kv_data(key, value).await
1636    }
1637
1638    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
1639        self.store.remove_kv_data(key).await
1640    }
1641
1642    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
1643        let _guard = self.lock.lock().await;
1644        self.store.save_changes(changes).await
1645    }
1646
1647    async fn get_presence_event(
1648        &self,
1649        user_id: &UserId,
1650    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
1651        self.store.get_presence_event(user_id).await
1652    }
1653
1654    async fn get_presence_events(
1655        &self,
1656        user_ids: &[OwnedUserId],
1657    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
1658        self.store.get_presence_events(user_ids).await
1659    }
1660
1661    async fn get_state_event(
1662        &self,
1663        room_id: &RoomId,
1664        event_type: StateEventType,
1665        state_key: &str,
1666    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
1667        self.store.get_state_event(room_id, event_type, state_key).await
1668    }
1669
1670    async fn get_state_events(
1671        &self,
1672        room_id: &RoomId,
1673        event_type: StateEventType,
1674    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1675        self.store.get_state_events(room_id, event_type).await
1676    }
1677
1678    async fn get_state_events_for_keys(
1679        &self,
1680        room_id: &RoomId,
1681        event_type: StateEventType,
1682        state_keys: &[&str],
1683    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
1684        self.store.get_state_events_for_keys(room_id, event_type, state_keys).await
1685    }
1686
1687    async fn get_profile(
1688        &self,
1689        room_id: &RoomId,
1690        user_id: &UserId,
1691    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
1692        self.store.get_profile(room_id, user_id).await
1693    }
1694
1695    async fn get_profiles<'a>(
1696        &self,
1697        room_id: &RoomId,
1698        user_ids: &'a [OwnedUserId],
1699    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
1700        self.store.get_profiles(room_id, user_ids).await
1701    }
1702
1703    async fn get_user_ids(
1704        &self,
1705        room_id: &RoomId,
1706        memberships: RoomMemberships,
1707    ) -> Result<Vec<OwnedUserId>, Self::Error> {
1708        self.store.get_user_ids(room_id, memberships).await
1709    }
1710
1711    async fn get_room_infos(
1712        &self,
1713        room_load_settings: &RoomLoadSettings,
1714    ) -> Result<Vec<RoomInfo>, Self::Error> {
1715        self.store.get_room_infos(room_load_settings).await
1716    }
1717
1718    async fn get_users_with_display_name(
1719        &self,
1720        room_id: &RoomId,
1721        display_name: &DisplayName,
1722    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
1723        self.store.get_users_with_display_name(room_id, display_name).await
1724    }
1725
1726    async fn get_users_with_display_names<'a>(
1727        &self,
1728        room_id: &RoomId,
1729        display_names: &'a [DisplayName],
1730    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
1731        self.store.get_users_with_display_names(room_id, display_names).await
1732    }
1733
1734    async fn get_account_data_event(
1735        &self,
1736        event_type: GlobalAccountDataEventType,
1737    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
1738        self.store.get_account_data_event(event_type).await
1739    }
1740
1741    async fn get_room_account_data_event(
1742        &self,
1743        room_id: &RoomId,
1744        event_type: RoomAccountDataEventType,
1745    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
1746        self.store.get_room_account_data_event(room_id, event_type).await
1747    }
1748
1749    async fn get_user_room_receipt_event(
1750        &self,
1751        room_id: &RoomId,
1752        receipt_type: ReceiptType,
1753        receipt_thread: &ReceiptThread,
1754        user_id: &UserId,
1755    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
1756        self.store.get_user_room_receipt_event(room_id, receipt_type, receipt_thread, user_id).await
1757    }
1758
1759    async fn get_event_room_receipt_events(
1760        &self,
1761        room_id: &RoomId,
1762        receipt_type: ReceiptType,
1763        receipt_thread: &ReceiptThread,
1764        event_id: &EventId,
1765    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
1766        self.store
1767            .get_event_room_receipt_events(room_id, receipt_type, receipt_thread, event_id)
1768            .await
1769    }
1770
1771    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1772        self.store.get_custom_value(key).await
1773    }
1774
1775    async fn set_custom_value(
1776        &self,
1777        key: &[u8],
1778        value: Vec<u8>,
1779    ) -> Result<Option<Vec<u8>>, Self::Error> {
1780        self.store.set_custom_value(key, value).await
1781    }
1782
1783    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
1784        self.store.remove_custom_value(key).await
1785    }
1786
1787    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
1788        let _guard = self.lock.lock().await;
1789        self.store.remove_room(room_id).await
1790    }
1791
1792    async fn save_send_queue_request(
1793        &self,
1794        room_id: &RoomId,
1795        transaction_id: OwnedTransactionId,
1796        created_at: MilliSecondsSinceUnixEpoch,
1797        request: QueuedRequestKind,
1798        priority: usize,
1799    ) -> Result<(), Self::Error> {
1800        self.store
1801            .save_send_queue_request(room_id, transaction_id, created_at, request, priority)
1802            .await
1803    }
1804
1805    async fn update_send_queue_request(
1806        &self,
1807        room_id: &RoomId,
1808        transaction_id: &TransactionId,
1809        content: QueuedRequestKind,
1810    ) -> Result<bool, Self::Error> {
1811        self.store.update_send_queue_request(room_id, transaction_id, content).await
1812    }
1813
1814    async fn remove_send_queue_request(
1815        &self,
1816        room_id: &RoomId,
1817        transaction_id: &TransactionId,
1818    ) -> Result<bool, Self::Error> {
1819        self.store.remove_send_queue_request(room_id, transaction_id).await
1820    }
1821
1822    async fn load_send_queue_requests(
1823        &self,
1824        room_id: &RoomId,
1825    ) -> Result<Vec<QueuedRequest>, Self::Error> {
1826        self.store.load_send_queue_requests(room_id).await
1827    }
1828
1829    async fn update_send_queue_request_status(
1830        &self,
1831        room_id: &RoomId,
1832        transaction_id: &TransactionId,
1833        error: Option<QueueWedgeError>,
1834    ) -> Result<(), Self::Error> {
1835        self.store.update_send_queue_request_status(room_id, transaction_id, error).await
1836    }
1837
1838    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
1839        self.store.load_rooms_with_unsent_requests().await
1840    }
1841
1842    async fn save_dependent_queued_request(
1843        &self,
1844        room_id: &RoomId,
1845        parent_txn_id: &TransactionId,
1846        own_txn_id: ChildTransactionId,
1847        created_at: MilliSecondsSinceUnixEpoch,
1848        content: DependentQueuedRequestKind,
1849    ) -> Result<(), Self::Error> {
1850        self.store
1851            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
1852            .await
1853    }
1854
1855    async fn mark_dependent_queued_requests_as_ready(
1856        &self,
1857        room_id: &RoomId,
1858        parent_txn_id: &TransactionId,
1859        sent_parent_key: SentRequestKey,
1860    ) -> Result<usize, Self::Error> {
1861        self.store
1862            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
1863            .await
1864    }
1865
1866    async fn update_dependent_queued_request(
1867        &self,
1868        room_id: &RoomId,
1869        own_transaction_id: &ChildTransactionId,
1870        new_content: DependentQueuedRequestKind,
1871    ) -> Result<bool, Self::Error> {
1872        self.store.update_dependent_queued_request(room_id, own_transaction_id, new_content).await
1873    }
1874
1875    async fn remove_dependent_queued_request(
1876        &self,
1877        room: &RoomId,
1878        own_txn_id: &ChildTransactionId,
1879    ) -> Result<bool, Self::Error> {
1880        self.store.remove_dependent_queued_request(room, own_txn_id).await
1881    }
1882
1883    async fn load_dependent_queued_requests(
1884        &self,
1885        room: &RoomId,
1886    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
1887        self.store.load_dependent_queued_requests(room).await
1888    }
1889
1890    async fn upsert_thread_subscriptions(
1891        &self,
1892        updates: Vec<(&RoomId, &EventId, StoredThreadSubscription)>,
1893    ) -> Result<(), Self::Error> {
1894        self.store.upsert_thread_subscriptions(updates).await
1895    }
1896
1897    async fn load_thread_subscription(
1898        &self,
1899        room: &RoomId,
1900        thread_id: &EventId,
1901    ) -> Result<Option<StoredThreadSubscription>, Self::Error> {
1902        self.store.load_thread_subscription(room, thread_id).await
1903    }
1904
1905    async fn remove_thread_subscription(
1906        &self,
1907        room: &RoomId,
1908        thread_id: &EventId,
1909    ) -> Result<(), Self::Error> {
1910        self.store.remove_thread_subscription(room, thread_id).await
1911    }
1912
1913    async fn get_global_profile(
1914        &self,
1915        user_id: &UserId,
1916    ) -> Result<Option<UserProfile>, Self::Error> {
1917        self.store.get_global_profile(user_id).await
1918    }
1919
1920    async fn get_global_profiles<'a>(
1921        &self,
1922        user_ids: &'a [OwnedUserId],
1923    ) -> Result<BTreeMap<&'a UserId, UserProfile>, Self::Error> {
1924        self.store.get_global_profiles(user_ids).await
1925    }
1926
1927    async fn close(&self) -> Result<(), Self::Error> {
1928        self.store.close().await
1929    }
1930
1931    async fn reopen(&self) -> Result<(), Self::Error> {
1932        self.store.reopen().await
1933    }
1934
1935    async fn optimize(&self) -> Result<(), Self::Error> {
1936        self.store.optimize().await
1937    }
1938
1939    async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
1940        self.store.get_size().await
1941    }
1942}
1943
1944/// Convenience functionality for state stores.
1945#[cfg_attr(target_family = "wasm", async_trait(?Send))]
1946#[cfg_attr(not(target_family = "wasm"), async_trait)]
1947pub trait StateStoreExt: StateStore {
1948    /// Get a specific state event of statically-known type.
1949    ///
1950    /// # Arguments
1951    ///
1952    /// * `room_id` - The id of the room the state event was received for.
1953    async fn get_state_event_static<C>(
1954        &self,
1955        room_id: &RoomId,
1956    ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
1957    where
1958        C: StaticEventContent<IsPrefix = ruma::events::False>
1959            + StaticStateEventContent<StateKey = EmptyStateKey>
1960            + RedactContent,
1961        C::Redacted: RedactedStateEventContent,
1962    {
1963        Ok(self.get_state_event(room_id, C::TYPE.into(), "").await?.map(|raw| raw.cast()))
1964    }
1965
1966    /// Get a specific state event of statically-known type.
1967    ///
1968    /// # Arguments
1969    ///
1970    /// * `room_id` - The id of the room the state event was received for.
1971    async fn get_state_event_static_for_key<C, K>(
1972        &self,
1973        room_id: &RoomId,
1974        state_key: &K,
1975    ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
1976    where
1977        C: StaticEventContent<IsPrefix = ruma::events::False>
1978            + StaticStateEventContent
1979            + RedactContent,
1980        C::StateKey: Borrow<K>,
1981        C::Redacted: RedactedStateEventContent,
1982        K: AsRef<str> + ?Sized + Sync,
1983    {
1984        Ok(self
1985            .get_state_event(room_id, C::TYPE.into(), state_key.as_ref())
1986            .await?
1987            .map(|raw| raw.cast()))
1988    }
1989
1990    /// Get a list of state events of a statically-known type for a given room.
1991    ///
1992    /// # Arguments
1993    ///
1994    /// * `room_id` - The id of the room to find events for.
1995    async fn get_state_events_static<C>(
1996        &self,
1997        room_id: &RoomId,
1998    ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
1999    where
2000        C: StaticEventContent<IsPrefix = ruma::events::False>
2001            + StaticStateEventContent
2002            + RedactContent,
2003        C::Redacted: RedactedStateEventContent,
2004    {
2005        // FIXME: Could be more efficient, if we had streaming store accessor
2006        // functions
2007        Ok(self
2008            .get_state_events(room_id, C::TYPE.into())
2009            .await?
2010            .into_iter()
2011            .map(|raw| raw.cast())
2012            .collect())
2013    }
2014
2015    /// Get a list of state events of a statically-known type for a given room
2016    /// and given state keys.
2017    ///
2018    /// # Arguments
2019    ///
2020    /// - `room_id` - The id of the room to find events for.
2021    /// - `state_keys` - The list of state keys to find.
2022    async fn get_state_events_for_keys_static<'a, C, K, I>(
2023        &self,
2024        room_id: &RoomId,
2025        state_keys: I,
2026    ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
2027    where
2028        C: StaticEventContent<IsPrefix = ruma::events::False>
2029            + StaticStateEventContent
2030            + RedactContent,
2031        C::StateKey: Borrow<K>,
2032        C::Redacted: RedactedStateEventContent,
2033        K: AsRef<str> + Sized + Sync + 'a,
2034        I: IntoIterator<Item = &'a K> + Send,
2035        I::IntoIter: Send,
2036    {
2037        Ok(self
2038            .get_state_events_for_keys(
2039                room_id,
2040                C::TYPE.into(),
2041                &state_keys.into_iter().map(|k| k.as_ref()).collect::<Vec<_>>(),
2042            )
2043            .await?
2044            .into_iter()
2045            .map(|raw| raw.cast())
2046            .collect())
2047    }
2048
2049    /// Get an event of a statically-known type from the account data store.
2050    async fn get_account_data_event_static<C>(
2051        &self,
2052    ) -> Result<Option<Raw<GlobalAccountDataEvent<C>>>, Self::Error>
2053    where
2054        C: StaticEventContent<IsPrefix = ruma::events::False> + GlobalAccountDataEventContent,
2055    {
2056        Ok(self.get_account_data_event(C::TYPE.into()).await?.map(Raw::cast_unchecked))
2057    }
2058
2059    /// Get an event of a statically-known type from the room account data
2060    /// store.
2061    ///
2062    /// # Arguments
2063    ///
2064    /// - `room_id` - The id of the room for which the room account data event
2065    ///   should be fetched.
2066    async fn get_room_account_data_event_static<C>(
2067        &self,
2068        room_id: &RoomId,
2069    ) -> Result<Option<Raw<RoomAccountDataEvent<C>>>, Self::Error>
2070    where
2071        C: StaticEventContent<IsPrefix = ruma::events::False> + RoomAccountDataEventContent,
2072    {
2073        Ok(self
2074            .get_room_account_data_event(room_id, C::TYPE.into())
2075            .await?
2076            .map(Raw::cast_unchecked))
2077    }
2078
2079    /// Get the `MemberEvent` for the given state key in the given room id.
2080    ///
2081    /// # Arguments
2082    ///
2083    /// * `room_id` - The room id the member event belongs to.
2084    ///
2085    /// * `state_key` - The user id that the member event defines the state for.
2086    async fn get_member_event(
2087        &self,
2088        room_id: &RoomId,
2089        state_key: &UserId,
2090    ) -> Result<Option<RawMemberEvent>, Self::Error> {
2091        self.get_state_event_static_for_key(room_id, state_key).await
2092    }
2093}
2094
2095#[cfg_attr(target_family = "wasm", async_trait(?Send))]
2096#[cfg_attr(not(target_family = "wasm"), async_trait)]
2097impl<T: StateStore + ?Sized> StateStoreExt for T {}
2098
2099/// A type-erased [`StateStore`].
2100pub type DynStateStore = dyn StateStore<Error = StoreError>;
2101
2102/// A type that can be type-erased into `Arc<dyn StateStore>`.
2103///
2104/// This trait is not meant to be implemented directly outside
2105/// `matrix-sdk-crypto`, but it is automatically implemented for everything that
2106/// implements `StateStore`.
2107pub trait IntoStateStore {
2108    #[doc(hidden)]
2109    fn into_state_store(self) -> Arc<DynStateStore>;
2110}
2111
2112impl<T> IntoStateStore for T
2113where
2114    T: StateStore + Sized + 'static,
2115{
2116    fn into_state_store(self) -> Arc<DynStateStore> {
2117        Arc::new(EraseStateStoreError(self))
2118    }
2119}
2120
2121/// Serialisable representation of get_supported_versions::Response.
2122#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
2123pub struct SupportedVersionsResponse {
2124    /// Versions supported by the remote server.
2125    pub versions: Vec<String>,
2126
2127    /// List of unstable features and their enablement status.
2128    pub unstable_features: BTreeMap<String, bool>,
2129}
2130
2131impl SupportedVersionsResponse {
2132    /// Extracts known Matrix versions and features from the un-typed lists of
2133    /// strings.
2134    ///
2135    /// Note: Matrix versions and features that Ruma cannot parse, or does not
2136    /// know about, are discarded.
2137    pub fn supported_versions(&self) -> SupportedVersions {
2138        let mut supported_versions =
2139            SupportedVersions::from_parts(&self.versions, &self.unstable_features);
2140
2141        // We need at least one supported version to be able to make requests,
2142        // so we default to Matrix 1.0.
2143        if supported_versions.versions.is_empty() {
2144            supported_versions.versions.insert(MatrixVersion::V1_0);
2145        }
2146
2147        supported_versions
2148    }
2149}
2150
2151#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
2152/// A serialisable representation of discover_homeserver::Response.
2153pub struct WellKnownResponse {
2154    /// Information about the homeserver to connect to.
2155    pub homeserver: HomeserverInfo,
2156
2157    /// Information about the identity server to connect to.
2158    pub identity_server: Option<IdentityServerInfo>,
2159
2160    /// Information about the tile server to use to display location data.
2161    pub tile_server: Option<TileServerInfo>,
2162
2163    /// A list of the available MatrixRTC foci, ordered by priority.
2164    pub rtc_foci: Vec<RtcTransport>,
2165}
2166
2167impl From<discover_homeserver::Response> for WellKnownResponse {
2168    fn from(response: discover_homeserver::Response) -> Self {
2169        Self {
2170            homeserver: response.homeserver,
2171            identity_server: response.identity_server,
2172            tile_server: response.tile_server,
2173            rtc_foci: response.rtc_foci,
2174        }
2175    }
2176}
2177
2178/// A value for key-value data that should be persisted into the store.
2179#[derive(Debug, Clone)]
2180pub enum StateStoreDataValue {
2181    /// The sync token.
2182    SyncToken(String),
2183
2184    /// The supported versions of the server.
2185    SupportedVersions(TtlValue<SupportedVersionsResponse>),
2186
2187    /// The well-known information of the server.
2188    WellKnown(TtlValue<Option<WellKnownResponse>>),
2189
2190    /// A filter with the given ID.
2191    Filter(String),
2192
2193    /// The user avatar url
2194    UserAvatarUrl(OwnedMxcUri),
2195
2196    /// A list of recently visited room identifiers for the current user
2197    RecentlyVisitedRooms(Vec<OwnedRoomId>),
2198
2199    /// Persistent data for
2200    /// `matrix_sdk_ui::unable_to_decrypt_hook::UtdHookManager`.
2201    UtdHookManagerData(GrowableBloom),
2202
2203    /// A unit value telling us that the client uploaded duplicate one-time
2204    /// keys.
2205    OneTimeKeyAlreadyUploaded,
2206
2207    /// A composer draft for the room. To learn more, see [`ComposerDraft`].
2208    ///
2209    /// [`ComposerDraft`]: Self::ComposerDraft
2210    ComposerDraft(ComposerDraft),
2211
2212    /// A list of knock request ids marked as seen in a room.
2213    SeenKnockRequests(BTreeMap<OwnedEventId, OwnedUserId>),
2214
2215    /// A list of tokens to continue thread subscriptions catchup.
2216    ///
2217    /// See documentation of [`ThreadSubscriptionCatchupToken`] for more
2218    /// details.
2219    ThreadSubscriptionsCatchupTokens(Vec<ThreadSubscriptionCatchupToken>),
2220
2221    /// The capabilities the homeserver supports or disables.
2222    HomeserverCapabilities(TtlValue<Capabilities>),
2223}
2224
2225/// Tokens to use when catching up on thread subscriptions.
2226///
2227/// These tokens are created when the client receives some thread subscriptions
2228/// from sync, but the sync indicates that there are more thread subscriptions
2229/// available on the server. In this case, it's expected that the client will
2230/// call the [MSC4308] companion endpoint to catch up (back-paginate) on
2231/// previous thread subscriptions.
2232///
2233/// [MSC4308]: https://github.com/matrix-org/matrix-spec-proposals/pull/4308
2234#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2235pub struct ThreadSubscriptionCatchupToken {
2236    /// The token to use as the lower bound when fetching new threads
2237    /// subscriptions.
2238    ///
2239    /// In sliding sync, this is the `prev_batch` value of a sliding sync
2240    /// response.
2241    pub from: String,
2242
2243    /// The token to use as the upper bound when fetching new threads
2244    /// subscriptions.
2245    ///
2246    /// In sliding sync, it must be set to the `pos` value of the sliding sync
2247    /// _request_, which response received a `prev_batch` token.
2248    pub to: Option<String>,
2249}
2250
2251/// Current draft of the composer for the room.
2252#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2253pub struct ComposerDraft {
2254    /// The draft content in plain text.
2255    pub plain_text: String,
2256    /// If the message is formatted in HTML, the HTML representation of the
2257    /// message.
2258    pub html_text: Option<String>,
2259    /// The type of draft.
2260    pub draft_type: ComposerDraftType,
2261    /// Attachments associated with this draft.
2262    #[serde(default)]
2263    pub attachments: Vec<DraftAttachment>,
2264}
2265
2266/// An attachment stored with a composer draft.
2267#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2268pub struct DraftAttachment {
2269    /// The filename of the attachment.
2270    pub filename: String,
2271    /// The attachment content with type-specific data.
2272    pub content: DraftAttachmentContent,
2273}
2274
2275/// The content of a draft attachment with type-specific data.
2276#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2277#[serde(tag = "type")]
2278pub enum DraftAttachmentContent {
2279    /// Image attachment.
2280    Image {
2281        /// The image file data.
2282        #[serde(with = "serde_bytes")]
2283        data: Vec<u8>,
2284        /// MIME type.
2285        mimetype: Option<String>,
2286        /// File size in bytes.
2287        size: Option<u64>,
2288        /// Width in pixels.
2289        width: Option<u64>,
2290        /// Height in pixels.
2291        height: Option<u64>,
2292        /// BlurHash string.
2293        blurhash: Option<String>,
2294        /// Optional thumbnail.
2295        thumbnail: Option<DraftThumbnail>,
2296    },
2297    /// Video attachment.
2298    Video {
2299        /// The video file data.
2300        #[serde(with = "serde_bytes")]
2301        data: Vec<u8>,
2302        /// MIME type.
2303        mimetype: Option<String>,
2304        /// File size in bytes.
2305        size: Option<u64>,
2306        /// Width in pixels.
2307        width: Option<u64>,
2308        /// Height in pixels.
2309        height: Option<u64>,
2310        /// Duration.
2311        duration: Option<std::time::Duration>,
2312        /// BlurHash string.
2313        blurhash: Option<String>,
2314        /// Optional thumbnail.
2315        thumbnail: Option<DraftThumbnail>,
2316    },
2317    /// Audio attachment.
2318    Audio {
2319        /// The audio file data.
2320        #[serde(with = "serde_bytes")]
2321        data: Vec<u8>,
2322        /// MIME type.
2323        mimetype: Option<String>,
2324        /// File size in bytes.
2325        size: Option<u64>,
2326        /// Duration.
2327        duration: Option<std::time::Duration>,
2328    },
2329    /// Generic file attachment.
2330    File {
2331        /// The file data.
2332        #[serde(with = "serde_bytes")]
2333        data: Vec<u8>,
2334        /// MIME type.
2335        mimetype: Option<String>,
2336        /// File size in bytes.
2337        size: Option<u64>,
2338    },
2339}
2340
2341/// Thumbnail data for a draft attachment.
2342#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2343pub struct DraftThumbnail {
2344    /// The filename of the thumbnail.
2345    pub filename: String,
2346    /// The thumbnail image data.
2347    #[serde(with = "serde_bytes")]
2348    pub data: Vec<u8>,
2349    /// MIME type of the thumbnail.
2350    pub mimetype: Option<String>,
2351    /// Width in pixels.
2352    pub width: Option<u64>,
2353    /// Height in pixels.
2354    pub height: Option<u64>,
2355    /// File size in bytes.
2356    pub size: Option<u64>,
2357}
2358
2359/// The type of draft of the composer.
2360#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2361pub enum ComposerDraftType {
2362    /// The draft is a new message.
2363    NewMessage,
2364    /// The draft is a reply to an event.
2365    Reply {
2366        /// The ID of the event being replied to.
2367        event_id: OwnedEventId,
2368    },
2369    /// The draft is an edit of an event.
2370    Edit {
2371        /// The ID of the event being edited.
2372        event_id: OwnedEventId,
2373    },
2374}
2375
2376impl StateStoreDataValue {
2377    /// Get this value if it is a sync token.
2378    pub fn into_sync_token(self) -> Option<String> {
2379        as_variant!(self, Self::SyncToken)
2380    }
2381
2382    /// Get this value if it is a filter.
2383    pub fn into_filter(self) -> Option<String> {
2384        as_variant!(self, Self::Filter)
2385    }
2386
2387    /// Get this value if it is a user avatar url.
2388    pub fn into_user_avatar_url(self) -> Option<OwnedMxcUri> {
2389        as_variant!(self, Self::UserAvatarUrl)
2390    }
2391
2392    /// Get this value if it is a list of recently visited rooms.
2393    pub fn into_recently_visited_rooms(self) -> Option<Vec<OwnedRoomId>> {
2394        as_variant!(self, Self::RecentlyVisitedRooms)
2395    }
2396
2397    /// Get this value if it is the data for the `UtdHookManager`.
2398    pub fn into_utd_hook_manager_data(self) -> Option<GrowableBloom> {
2399        as_variant!(self, Self::UtdHookManagerData)
2400    }
2401
2402    /// Get this value if it is a composer draft.
2403    pub fn into_composer_draft(self) -> Option<ComposerDraft> {
2404        as_variant!(self, Self::ComposerDraft)
2405    }
2406
2407    /// Get this value if it is the supported versions metadata.
2408    pub fn into_supported_versions(self) -> Option<TtlValue<SupportedVersionsResponse>> {
2409        as_variant!(self, Self::SupportedVersions)
2410    }
2411
2412    /// Get this value if it is the well-known metadata.
2413    pub fn into_well_known(self) -> Option<TtlValue<Option<WellKnownResponse>>> {
2414        as_variant!(self, Self::WellKnown)
2415    }
2416
2417    /// Get this value if it is the data for the ignored join requests.
2418    pub fn into_seen_knock_requests(self) -> Option<BTreeMap<OwnedEventId, OwnedUserId>> {
2419        as_variant!(self, Self::SeenKnockRequests)
2420    }
2421
2422    /// Get this value if it is the data for the thread subscriptions catchup
2423    /// tokens.
2424    pub fn into_thread_subscriptions_catchup_tokens(
2425        self,
2426    ) -> Option<Vec<ThreadSubscriptionCatchupToken>> {
2427        as_variant!(self, Self::ThreadSubscriptionsCatchupTokens)
2428    }
2429
2430    /// Get this value if it is the data for the capabilities the homeserver
2431    /// supports or disables.
2432    pub fn into_homeserver_capabilities(self) -> Option<TtlValue<Capabilities>> {
2433        as_variant!(self, Self::HomeserverCapabilities)
2434    }
2435}
2436
2437/// A key for key-value data.
2438#[derive(Debug, Clone, Copy)]
2439pub enum StateStoreDataKey<'a> {
2440    /// The sync token.
2441    SyncToken,
2442
2443    /// The supported versions of the server,
2444    SupportedVersions,
2445
2446    /// The well-known information of the server,
2447    WellKnown,
2448
2449    /// A filter with the given name.
2450    Filter(&'a str),
2451
2452    /// Avatar URL
2453    UserAvatarUrl(&'a UserId),
2454
2455    /// Recently visited room identifiers
2456    RecentlyVisitedRooms(&'a UserId),
2457
2458    /// Persistent data for
2459    /// `matrix_sdk_ui::unable_to_decrypt_hook::UtdHookManager`.
2460    UtdHookManagerData,
2461
2462    /// Data remembering if the client already reported that it has uploaded
2463    /// duplicate one-time keys.
2464    OneTimeKeyAlreadyUploaded,
2465
2466    /// A composer draft for the room. To learn more, see [`ComposerDraft`].
2467    ///
2468    /// [`ComposerDraft`]: Self::ComposerDraft
2469    ComposerDraft(&'a RoomId, Option<&'a EventId>),
2470
2471    /// A list of knock request ids marked as seen in a room.
2472    SeenKnockRequests(&'a RoomId),
2473
2474    /// A list of thread subscriptions catchup tokens.
2475    ThreadSubscriptionsCatchupTokens,
2476
2477    /// A list of capabilities that the homeserver supports.
2478    HomeserverCapabilities,
2479}
2480
2481impl StateStoreDataKey<'_> {
2482    /// Key to use for the [`SyncToken`][Self::SyncToken] variant.
2483    pub const SYNC_TOKEN: &'static str = "sync_token";
2484
2485    /// Key to use for the [`SupportedVersions`][Self::SupportedVersions]
2486    /// variant.
2487    // Note: this is the old name, kept for backwards compatibility.
2488    pub const SUPPORTED_VERSIONS: &'static str = "server_capabilities";
2489
2490    /// Key to use for the [`WellKnown`][Self::WellKnown] variant.
2491    pub const WELL_KNOWN: &'static str = "well_known";
2492
2493    /// Key prefix to use for the [`Filter`][Self::Filter] variant.
2494    pub const FILTER: &'static str = "filter";
2495
2496    /// Key prefix to use for the [`UserAvatarUrl`][Self::UserAvatarUrl]
2497    /// variant.
2498    pub const USER_AVATAR_URL: &'static str = "user_avatar_url";
2499
2500    /// Key prefix to use for the
2501    /// [`RecentlyVisitedRooms`][Self::RecentlyVisitedRooms] variant.
2502    pub const RECENTLY_VISITED_ROOMS: &'static str = "recently_visited_rooms";
2503
2504    /// Key to use for the [`UtdHookManagerData`][Self::UtdHookManagerData]
2505    /// variant.
2506    pub const UTD_HOOK_MANAGER_DATA: &'static str = "utd_hook_manager_data";
2507
2508    /// Key to use for the flag remembering that we already reported that we
2509    /// uploaded duplicate one-time keys.
2510    pub const ONE_TIME_KEY_ALREADY_UPLOADED: &'static str = "one_time_key_already_uploaded";
2511
2512    /// Key prefix to use for the [`ComposerDraft`][Self::ComposerDraft]
2513    /// variant.
2514    pub const COMPOSER_DRAFT: &'static str = "composer_draft";
2515
2516    /// Key prefix to use for the [`SeenKnockRequests`][Self::SeenKnockRequests]
2517    /// variant.
2518    pub const SEEN_KNOCK_REQUESTS: &'static str = "seen_knock_requests";
2519
2520    /// Key prefix to use for the
2521    /// [`ThreadSubscriptionsCatchupTokens`][Self::ThreadSubscriptionsCatchupTokens]
2522    /// variant.
2523    pub const THREAD_SUBSCRIPTIONS_CATCHUP_TOKENS: &'static str =
2524        "thread_subscriptions_catchup_tokens";
2525
2526    /// Key prefix to use for the homeserver's [`Capabilities`].
2527    pub const HOMESERVER_CAPABILITIES: &'static str = "homeserver_capabilities";
2528}
2529
2530/// Compare two thread subscription changes bump stamps, given a fixed room and
2531/// thread root event id pair.
2532///
2533/// May update the newer one to keep the previous one if needed, under some
2534/// conditions.
2535///
2536/// Returns true if the new subscription should be stored, or false if the new
2537/// subscription should be ignored.
2538pub fn compare_thread_subscription_bump_stamps(
2539    previous: Option<u64>,
2540    new: &mut Option<u64>,
2541) -> bool {
2542    match (previous, &new) {
2543        // If the previous subscription had a bump stamp, and the new one
2544        // doesn't, keep the previous one; it should be updated soon via sync
2545        // anyways.
2546        (Some(prev_bump), None) => {
2547            *new = Some(prev_bump);
2548        }
2549
2550        // If the previous bump stamp is newer than the new one, don't store the value at all.
2551        (Some(prev_bump), Some(new_bump)) if *new_bump <= prev_bump => {
2552            return false;
2553        }
2554
2555        // In all other cases, keep the new bumpstamp.
2556        _ => {}
2557    }
2558
2559    true
2560}
2561
2562#[cfg(test)]
2563mod tests {
2564    mod save_locked_state_store {
2565        use std::time::Duration;
2566
2567        use assert_matches::assert_matches;
2568        use futures_util::future::{self, Either};
2569        #[cfg(all(target_family = "wasm", target_os = "unknown"))]
2570        use gloo_timers::future::sleep;
2571        use matrix_sdk_common::executor::spawn;
2572        use matrix_sdk_test::async_test;
2573        use ruma::room_id;
2574        use tokio::sync::Mutex;
2575        #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
2576        use tokio::time::sleep;
2577
2578        use crate::{
2579            StateChanges, StateStore,
2580            store::{IntoStateStore, MemoryStore, Result, SaveLockedStateStore},
2581        };
2582
2583        async fn get_store() -> Result<impl StateStore> {
2584            Ok(SaveLockedStateStore::new(MemoryStore::new()))
2585        }
2586
2587        statestore_integration_tests!();
2588
2589        #[async_test]
2590        async fn test_save_changes_only_accepts_guard_for_underlying_mutex() {
2591            let state_store = SaveLockedStateStore::new(MemoryStore::new());
2592            let state_changes = StateChanges::default();
2593            state_store
2594                .save_changes_with_guard(&state_store.lock().lock().await, &state_changes)
2595                .await
2596                .expect("state store accepts guard for underlying mutex");
2597
2598            let mutex = Mutex::new(());
2599            state_store
2600                .save_changes_with_guard(&mutex.lock().await, &state_changes)
2601                .await
2602                .expect_err("state store does not accept guard for unknown mutex");
2603        }
2604
2605        #[async_test]
2606        async fn test_remove_room_only_accepts_guard_for_underlying_mutex() {
2607            let state_store = SaveLockedStateStore::new(MemoryStore::new());
2608            let room_id = room_id!("!room");
2609            state_store
2610                .remove_room_with_guard(&state_store.lock().lock().await, room_id)
2611                .await
2612                .expect("state store accepts guard for underlying mutex");
2613
2614            let mutex = Mutex::new(());
2615            state_store
2616                .remove_room_with_guard(&mutex.lock().await, room_id)
2617                .await
2618                .expect_err("state store does not accept guard for unknown mutex");
2619        }
2620
2621        #[derive(Debug)]
2622        struct Elapsed;
2623
2624        async fn timeout<F: Future + Unpin>(
2625            duration: Duration,
2626            f: F,
2627        ) -> Result<F::Output, Elapsed> {
2628            #[cfg(all(target_family = "wasm", target_os = "unknown"))]
2629            {
2630                match future::select(sleep(duration), f).await {
2631                    Either::Left(_) => return Err(Elapsed),
2632                    Either::Right((output, _)) => Ok(output),
2633                }
2634            }
2635            #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
2636            {
2637                tokio::time::timeout(duration, f).await.map_err(|_| Elapsed)
2638            }
2639        }
2640
2641        #[async_test]
2642        async fn test_state_store_waits_to_acquire_lock_before_saving_changes() {
2643            let state_store = SaveLockedStateStore::new(MemoryStore::new().into_state_store());
2644
2645            // Acquire lock and hold it for 5 seconds
2646            let lock_task = spawn({
2647                let state_store = state_store.clone();
2648                async move {
2649                    let lock = state_store.lock();
2650                    let _guard = lock.lock().await;
2651                    sleep(Duration::from_secs(5)).await;
2652                }
2653            });
2654
2655            // Try to save changes to the state store while the lock is held by
2656            // another task
2657            let save_task =
2658                spawn(async move { state_store.save_changes(&StateChanges::default()).await });
2659
2660            // Ensure that the second task does not progress until the first
2661            // task has completed and therefore release the save lock
2662            assert_matches!(future::select(lock_task, save_task).await, Either::Left((_, save_task)) => {
2663                timeout(Duration::from_millis(100), save_task)
2664                    .await
2665                    .expect("task completes before timeout")
2666                    .expect("task completes successfully")
2667                    .expect("task saves changes");
2668            });
2669        }
2670
2671        #[async_test]
2672        async fn test_state_store_waits_to_acquire_lock_before_removing_room() {
2673            let state_store = SaveLockedStateStore::new(MemoryStore::new().into_state_store());
2674
2675            // Acquire lock and hold it for 5 seconds
2676            let lock_task = spawn({
2677                let state_store = state_store.clone();
2678                async move {
2679                    let lock = state_store.lock();
2680                    let _guard = lock.lock().await;
2681                    sleep(Duration::from_secs(5)).await;
2682                }
2683            });
2684
2685            // Try to remove room from the state store while the lock is held by
2686            // another task
2687            let remove_task =
2688                spawn(async move { state_store.remove_room(room_id!("!room")).await });
2689
2690            // Ensure that the second task does not progress until the first
2691            // task has completed and therefore release the save lock
2692            assert_matches!(future::select(lock_task, remove_task).await, Either::Left((_, remove_task)) => {
2693                timeout(Duration::from_millis(100), remove_task)
2694                    .await
2695                    .expect("task completes before timeout")
2696                    .expect("task completes successfully")
2697                    .expect("task saves changes");
2698            });
2699        }
2700    }
2701}