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