1mod error;
50mod latest_event;
51mod room_latest_events;
52
53use std::{
54 collections::HashMap,
55 ops::{ControlFlow, DerefMut, Not},
56 sync::Arc,
57};
58
59pub use error::LatestEventsError;
60use eyeball::{AsyncLock, Subscriber};
61pub(crate) use latest_event::filter_timeline_event;
62use latest_event::{LatestEvent, With};
63pub use latest_event::{LatestEventValue, LocalLatestEventValue, RemoteLatestEventValue};
64use matrix_sdk_base::{RoomInfoNotableUpdate, RoomInfoNotableUpdateReasons, timer};
65use matrix_sdk_common::executor::{AbortOnDrop, JoinHandleExt as _, spawn};
66use room_latest_events::{RoomLatestEvents, RoomLatestEventsWriteGuard};
67use ruma::{EventId, OwnedRoomId, RoomId};
68use tokio::{
69 select,
70 sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, broadcast, mpsc},
71};
72use tracing::{info, warn};
73
74use crate::{
75 client::WeakClient,
76 event_cache::{EventCache, RoomEventCacheGenericUpdate},
77 room::WeakRoom,
78 send_queue::{RoomSendQueueUpdate, SendQueue, SendQueueUpdate},
79};
80
81#[derive(Clone, Debug)]
83pub struct LatestEvents {
84 state: Arc<LatestEventsState>,
85}
86
87#[derive(Debug)]
89struct LatestEventsState {
90 registered_rooms: Arc<RegisteredRooms>,
92
93 _listen_task_handle: AbortOnDrop<()>,
95
96 _computation_task_handle: AbortOnDrop<()>,
98}
99
100impl LatestEvents {
101 pub(crate) fn new(
103 weak_client: WeakClient,
104 event_cache: EventCache,
105 send_queue: SendQueue,
106 room_info_updates: broadcast::Receiver<RoomInfoNotableUpdate>,
107 ) -> Self {
108 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
109
110 let registered_rooms =
111 Arc::new(RegisteredRooms::new(weak_client, &event_cache, &latest_event_queue_sender));
112
113 let listen_task_handle = spawn(listen_to_updates_task(
116 registered_rooms.clone(),
117 event_cache,
118 send_queue,
119 room_info_updates,
120 latest_event_queue_sender,
121 ))
122 .abort_on_drop();
123
124 let computation_task_handle = spawn(compute_latest_events_task(
126 registered_rooms.clone(),
127 latest_event_queue_receiver,
128 ))
129 .abort_on_drop();
130
131 Self {
132 state: Arc::new(LatestEventsState {
133 registered_rooms,
134 _listen_task_handle: listen_task_handle,
135 _computation_task_handle: computation_task_handle,
136 }),
137 }
138 }
139
140 pub async fn listen_to_room(&self, room_id: &RoomId) -> Result<bool, LatestEventsError> {
144 Ok(self.state.registered_rooms.for_room(room_id).await?.is_some())
145 }
146
147 #[cfg(test)]
151 pub async fn is_listening_to_room(&self, room_id: &RoomId) -> bool {
152 self.state.registered_rooms.rooms.read().await.contains_key(room_id)
153 }
154
155 pub async fn listen_and_subscribe_to_room(
161 &self,
162 room_id: &RoomId,
163 ) -> Result<Option<Subscriber<LatestEventValue, AsyncLock>>, LatestEventsError> {
164 let Some(room_latest_events) = self.state.registered_rooms.for_room(room_id).await? else {
165 return Ok(None);
166 };
167
168 let room_latest_events = room_latest_events.read().await;
169 let latest_event = room_latest_events.for_room();
170
171 Ok(Some(latest_event.subscribe().await))
172 }
173
174 pub async fn listen_to_thread(
179 &self,
180 room_id: &RoomId,
181 thread_id: &EventId,
182 ) -> Result<bool, LatestEventsError> {
183 Ok(self.state.registered_rooms.for_thread(room_id, thread_id).await?.is_some())
184 }
185
186 pub async fn listen_and_subscribe_to_thread(
192 &self,
193 room_id: &RoomId,
194 thread_id: &EventId,
195 ) -> Result<Option<Subscriber<LatestEventValue, AsyncLock>>, LatestEventsError> {
196 let Some(room_latest_events) =
197 self.state.registered_rooms.for_thread(room_id, thread_id).await?
198 else {
199 return Ok(None);
200 };
201
202 let room_latest_events = room_latest_events.read().await;
203 let latest_event = room_latest_events
204 .for_thread(thread_id)
205 .expect("The `LatestEvent` for the thread must have been created");
206
207 Ok(Some(latest_event.subscribe().await))
208 }
209
210 pub async fn forget_room(&self, room_id: &RoomId) {
217 self.state.registered_rooms.forget_room(room_id).await;
218 }
219
220 pub async fn forget_thread(&self, room_id: &RoomId, thread_id: &EventId) {
228 self.state.registered_rooms.forget_thread(room_id, thread_id).await;
229 }
230}
231
232#[derive(Debug)]
233struct RegisteredRooms {
234 rooms: RwLock<HashMap<OwnedRoomId, RoomLatestEvents>>,
236
237 weak_client: WeakClient,
239
240 event_cache: EventCache,
242
243 latest_event_queue_sender: mpsc::UnboundedSender<LatestEventQueueUpdate>,
248}
249
250impl RegisteredRooms {
251 fn new(
252 weak_client: WeakClient,
253 event_cache: &EventCache,
254 latest_event_queue_sender: &mpsc::UnboundedSender<LatestEventQueueUpdate>,
255 ) -> Self {
256 Self {
257 rooms: RwLock::new(HashMap::default()),
258 weak_client,
259 event_cache: event_cache.clone(),
260 latest_event_queue_sender: latest_event_queue_sender.clone(),
261 }
262 }
263
264 async fn room_latest_event(
271 &self,
272 room_id: &RoomId,
273 thread_id: Option<&EventId>,
274 ) -> Result<Option<RwLockReadGuard<'_, RoomLatestEvents>>, LatestEventsError> {
275 fn create_and_insert_room_latest_events(
276 room_id: &RoomId,
277 rooms: &mut HashMap<OwnedRoomId, RoomLatestEvents>,
278 weak_client: &WeakClient,
279 event_cache: &EventCache,
280 latest_event_queue_sender: &mpsc::UnboundedSender<LatestEventQueueUpdate>,
281 ) {
282 let (room_latest_events, is_latest_event_value_none) =
283 With::unzip(RoomLatestEvents::new(
284 WeakRoom::new(weak_client.clone(), room_id.to_owned()),
285 event_cache,
286 ));
287
288 rooms.insert(room_id.to_owned(), room_latest_events);
290
291 if is_latest_event_value_none {
298 let _ = latest_event_queue_sender
299 .send(LatestEventQueueUpdate::EventCache { room_id: room_id.to_owned() });
300 }
301 }
302
303 Ok(match thread_id {
304 Some(thread_id) => {
310 let mut rooms = self.rooms.write().await;
311
312 if rooms.contains_key(room_id).not() {
315 create_and_insert_room_latest_events(
316 room_id,
317 rooms.deref_mut(),
318 &self.weak_client,
319 &self.event_cache,
320 &self.latest_event_queue_sender,
321 );
322 }
323
324 if let Some(room_latest_event) = rooms.get(room_id) {
325 let mut room_latest_event = room_latest_event.write().await;
326
327 if room_latest_event.has_thread(thread_id).not() {
330 room_latest_event.create_and_insert_latest_event_for_thread(thread_id);
331 }
332 }
333
334 RwLockWriteGuard::try_downgrade_map(rooms, |rooms| rooms.get(room_id)).ok()
335 }
336
337 None => {
340 match RwLockReadGuard::try_map(self.rooms.read().await, |rooms| rooms.get(room_id))
341 .ok()
342 {
343 value @ Some(_) => value,
344 None => {
345 let _timer = timer!(
346 tracing::Level::DEBUG,
347 format!("Creating `RoomLatestEvents` for {room_id:?}"),
348 );
349
350 let mut rooms = self.rooms.write().await;
351
352 if rooms.contains_key(room_id).not() {
353 create_and_insert_room_latest_events(
354 room_id,
355 rooms.deref_mut(),
356 &self.weak_client,
357 &self.event_cache,
358 &self.latest_event_queue_sender,
359 );
360 }
361
362 RwLockWriteGuard::try_downgrade_map(rooms, |rooms| rooms.get(room_id)).ok()
363 }
364 }
365 }
366 })
367 }
368
369 pub async fn for_room(
373 &self,
374 room_id: &RoomId,
375 ) -> Result<Option<RwLockReadGuard<'_, RoomLatestEvents>>, LatestEventsError> {
376 self.room_latest_event(room_id, None).await
377 }
378
379 pub async fn for_thread(
383 &self,
384 room_id: &RoomId,
385 thread_id: &EventId,
386 ) -> Result<Option<RwLockReadGuard<'_, RoomLatestEvents>>, LatestEventsError> {
387 self.room_latest_event(room_id, Some(thread_id)).await
388 }
389
390 pub async fn forget_room(&self, room_id: &RoomId) {
397 {
398 let mut rooms = self.rooms.write().await;
399
400 rooms.remove(room_id);
402 }
403 }
404
405 pub async fn forget_thread(&self, room_id: &RoomId, thread_id: &EventId) {
413 let rooms = self.rooms.read().await;
414
415 if let Some(room_latest_event) = rooms.get(room_id) {
417 let mut room_latest_event = room_latest_event.write().await;
418
419 drop(rooms);
421
422 room_latest_event.forget_thread(thread_id);
423 }
424 }
425}
426
427#[derive(Debug)]
430enum LatestEventQueueUpdate {
431 EventCache {
433 room_id: OwnedRoomId,
435 },
436
437 SendQueue {
439 room_id: OwnedRoomId,
441
442 update: RoomSendQueueUpdate,
444 },
445
446 RoomInfo {
450 room_id: OwnedRoomId,
452
453 reasons: RoomInfoNotableUpdateReasons,
455 },
456}
457
458async fn listen_to_updates_task(
467 registered_rooms: Arc<RegisteredRooms>,
468 event_cache: EventCache,
469 send_queue: SendQueue,
470 room_info_updates: broadcast::Receiver<RoomInfoNotableUpdate>,
471 latest_event_queue_sender: mpsc::UnboundedSender<LatestEventQueueUpdate>,
472) {
473 let mut event_cache_generic_updates_subscriber =
474 event_cache.subscribe_to_room_generic_updates();
475 let mut send_queue_generic_updates_subscriber = send_queue.subscribe();
476 let mut room_info_updates_subscriber = room_info_updates.resubscribe();
477
478 loop {
479 if listen_to_updates(
480 ®istered_rooms.rooms,
481 &mut event_cache_generic_updates_subscriber,
482 &mut send_queue_generic_updates_subscriber,
483 &mut room_info_updates_subscriber,
484 &latest_event_queue_sender,
485 )
486 .await
487 .is_break()
488 {
489 warn!("`listen_to_updates_task` has stopped");
490
491 break;
492 }
493 }
494}
495
496async fn listen_to_updates(
501 registered_rooms: &RwLock<HashMap<OwnedRoomId, RoomLatestEvents>>,
502 event_cache_generic_updates_subscriber: &mut broadcast::Receiver<RoomEventCacheGenericUpdate>,
503 send_queue_generic_updates_subscriber: &mut broadcast::Receiver<SendQueueUpdate>,
504 room_info_updates_subscriber: &mut broadcast::Receiver<RoomInfoNotableUpdate>,
505 latest_event_queue_sender: &mpsc::UnboundedSender<LatestEventQueueUpdate>,
506) -> ControlFlow<()> {
507 select! {
508 room_event_cache_generic_update = event_cache_generic_updates_subscriber.recv() => {
509 if let Ok(RoomEventCacheGenericUpdate { room_id }) = room_event_cache_generic_update {
510 if registered_rooms.read().await.contains_key(&room_id) {
511 let _ = latest_event_queue_sender.send(LatestEventQueueUpdate::EventCache {
512 room_id
513 });
514 }
515 } else {
516 warn!("`event_cache_generic_updates` channel has been closed");
517
518 return ControlFlow::Break(());
519 }
520 }
521
522 send_queue_generic_update = send_queue_generic_updates_subscriber.recv() => {
523 if let Ok(SendQueueUpdate { room_id, update }) = send_queue_generic_update {
524 if registered_rooms.read().await.contains_key(&room_id) {
525 let _ = latest_event_queue_sender.send(LatestEventQueueUpdate::SendQueue {
526 room_id,
527 update
528 });
529 }
530 } else {
531 warn!("`send_queue_generic_updates` channel has been closed");
532
533 return ControlFlow::Break(());
534 }
535 }
536
537 room_info_update = room_info_updates_subscriber.recv() => {
538 if let Ok(RoomInfoNotableUpdate { room_id, reasons }) = room_info_update {
539 if
541 reasons == RoomInfoNotableUpdateReasons::LATEST_EVENT ||
544
545 !reasons.contains(RoomInfoNotableUpdateReasons::MEMBERSHIP)
549 {
550 return ControlFlow::Continue(())
551 }
552
553 if registered_rooms.read().await.contains_key(&room_id) {
554 let _ = latest_event_queue_sender.send(LatestEventQueueUpdate::RoomInfo {
555 room_id,
556 reasons,
557 });
558 }
559 } else {
560 warn!("`room_info_updates` channel has been closed");
561
562 return ControlFlow::Break(());
563 }
564 }
565 }
566
567 ControlFlow::Continue(())
568}
569
570async fn compute_latest_events_task(
575 registered_rooms: Arc<RegisteredRooms>,
576 mut latest_event_queue_receiver: mpsc::UnboundedReceiver<LatestEventQueueUpdate>,
577) {
578 const BUFFER_SIZE: usize = 16;
579
580 let mut buffer = Vec::with_capacity(BUFFER_SIZE);
581
582 while latest_event_queue_receiver.recv_many(&mut buffer, BUFFER_SIZE).await > 0 {
583 compute_latest_events(®istered_rooms, &buffer).await;
584 buffer.clear();
585 }
586
587 warn!("`compute_latest_events_task` has stopped");
588}
589
590async fn compute_latest_events(
591 registered_rooms: &RegisteredRooms,
592 latest_event_queue_updates: &[LatestEventQueueUpdate],
593) {
594 async fn room_latest_events_write_guard(
595 registered_rooms: &RegisteredRooms,
596 room_id: &OwnedRoomId,
597 ) -> ControlFlow<RoomLatestEventsWriteGuard, ()> {
598 let rooms = registered_rooms.rooms.read().await;
599
600 if let Some(room_latest_events) = rooms.get(room_id) {
601 let room_latest_events = room_latest_events.write().await;
602
603 drop(rooms);
606
607 ControlFlow::Break(room_latest_events)
608 } else {
609 info!(?room_id, "Failed to find the room");
610
611 ControlFlow::Continue(())
612 }
613 }
614
615 for latest_event_queue_update in latest_event_queue_updates {
616 match latest_event_queue_update {
617 LatestEventQueueUpdate::EventCache { room_id } => {
618 let ControlFlow::Break(mut room_latest_events) =
619 room_latest_events_write_guard(registered_rooms, room_id).await
620 else {
621 continue;
622 };
623
624 room_latest_events.update_with_event_cache().await;
625 }
626
627 LatestEventQueueUpdate::SendQueue { room_id, update } => {
628 let ControlFlow::Break(mut room_latest_events) =
629 room_latest_events_write_guard(registered_rooms, room_id).await
630 else {
631 continue;
632 };
633
634 room_latest_events.update_with_send_queue(update).await;
635 }
636
637 LatestEventQueueUpdate::RoomInfo { room_id, reasons } => {
638 let ControlFlow::Break(mut room_latest_events) =
639 room_latest_events_write_guard(registered_rooms, room_id).await
640 else {
641 continue;
642 };
643
644 room_latest_events.update_with_room_info(*reasons).await;
645 }
646 }
647 }
648}
649
650#[cfg(test)]
651fn local_room_message(body: &str) -> LocalLatestEventValue {
652 use matrix_sdk_base::store::SerializableEventContent;
653 use ruma::{
654 MilliSecondsSinceUnixEpoch,
655 events::{AnyMessageLikeEventContent, room::message::RoomMessageEventContent},
656 };
657
658 LocalLatestEventValue {
659 timestamp: MilliSecondsSinceUnixEpoch::now(),
660 content: SerializableEventContent::new(&AnyMessageLikeEventContent::RoomMessage(
661 RoomMessageEventContent::text_plain(body),
662 ))
663 .unwrap(),
664 }
665}
666
667#[cfg(all(test, not(target_family = "wasm")))]
668mod tests {
669 use std::{collections::HashMap, ops::Not, time::Duration};
670
671 use assert_matches::assert_matches;
672 use matrix_sdk_base::{
673 RoomState,
674 deserialized_responses::TimelineEventKind,
675 linked_chunk::{ChunkIdentifier, LinkedChunkId, Position, Update},
676 };
677 use matrix_sdk_test::{
678 InvitedRoomBuilder, JoinedRoomBuilder, async_test, event_factory::EventFactory,
679 };
680 use ruma::{
681 MilliSecondsSinceUnixEpoch, OwnedTransactionId, event_id,
682 events::{
683 AnySyncMessageLikeEvent, AnySyncStateEvent, AnySyncTimelineEvent, SyncMessageLikeEvent,
684 room::member::{MembershipState, SyncRoomMemberEvent},
685 },
686 owned_event_id, owned_room_id, room_id, user_id,
687 };
688 use stream_assert::assert_pending;
689 use tokio::{task::yield_now, time::timeout};
690
691 use super::{
692 LatestEventValue, RegisteredRooms, RemoteLatestEventValue, RoomEventCacheGenericUpdate,
693 RoomInfoNotableUpdate, RoomInfoNotableUpdateReasons, RoomLatestEvents, RoomSendQueueUpdate,
694 RwLock, SendQueueUpdate, WeakClient, WeakRoom, With, broadcast, listen_to_updates, mpsc,
695 };
696 use crate::{
697 latest_events::{LatestEventQueueUpdate, local_room_message},
698 test_utils::mocks::MatrixMockServer,
699 };
700
701 #[async_test]
702 async fn test_latest_events_are_lazy() {
703 let room_id_0 = room_id!("!r0");
704 let room_id_1 = room_id!("!r1");
705 let room_id_2 = room_id!("!r2");
706 let thread_id_1_0 = event_id!("$ev1.0");
707 let thread_id_2_0 = event_id!("$ev2.0");
708
709 let server = MatrixMockServer::new().await;
710 let client = server.client_builder().build().await;
711
712 client.base_client().get_or_create_room(room_id_0, RoomState::Joined);
713 client.base_client().get_or_create_room(room_id_1, RoomState::Joined);
714 client.base_client().get_or_create_room(room_id_2, RoomState::Joined);
715
716 client.event_cache().subscribe().unwrap();
717
718 let latest_events = client.latest_events().await;
719
720 assert!(latest_events.state.registered_rooms.rooms.read().await.is_empty());
722
723 assert!(latest_events.listen_to_room(room_id_0).await.unwrap());
725 assert!(latest_events.listen_to_room(room_id_1).await.unwrap());
726
727 {
728 let rooms = latest_events.state.registered_rooms.rooms.read().await;
729 assert_eq!(rooms.len(), 2);
731 assert!(rooms.contains_key(room_id_0));
733 assert!(rooms.contains_key(room_id_1));
734
735 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
737 assert!(rooms.get(room_id_1).unwrap().read().await.per_thread().is_empty());
739 }
740
741 assert!(latest_events.listen_to_thread(room_id_1, thread_id_1_0).await.unwrap());
743 assert!(latest_events.listen_to_thread(room_id_2, thread_id_2_0).await.unwrap());
744
745 {
746 let rooms = latest_events.state.registered_rooms.rooms.read().await;
747 assert_eq!(rooms.len(), 3);
749 assert!(rooms.contains_key(room_id_0));
751 assert!(rooms.contains_key(room_id_1));
752 assert!(rooms.contains_key(room_id_2));
753
754 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
756 let room_1 = rooms.get(room_id_1).unwrap().read().await;
758 assert_eq!(room_1.per_thread().len(), 1);
759 assert!(room_1.per_thread().contains_key(thread_id_1_0));
761 let room_2 = rooms.get(room_id_2).unwrap().read().await;
763 assert_eq!(room_2.per_thread().len(), 1);
764 assert!(room_2.per_thread().contains_key(thread_id_2_0));
766 }
767 }
768
769 #[async_test]
770 async fn test_forget_room() {
771 let room_id_0 = room_id!("!r0");
772 let room_id_1 = room_id!("!r1");
773
774 let server = MatrixMockServer::new().await;
775 let client = server.client_builder().build().await;
776
777 client.base_client().get_or_create_room(room_id_0, RoomState::Joined);
778 client.base_client().get_or_create_room(room_id_1, RoomState::Joined);
779
780 client.event_cache().subscribe().unwrap();
781
782 let latest_events = client.latest_events().await;
783
784 assert!(latest_events.listen_to_room(room_id_0).await.unwrap());
786
787 {
788 let rooms = latest_events.state.registered_rooms.rooms.read().await;
789 assert_eq!(rooms.len(), 1);
791 assert!(rooms.contains_key(room_id_0));
793
794 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
796 }
797
798 latest_events.forget_room(room_id_0).await;
800
801 {
802 let rooms = latest_events.state.registered_rooms.rooms.read().await;
803 assert!(rooms.is_empty());
805 }
806 }
807
808 #[async_test]
809 async fn test_forget_thread() {
810 let room_id_0 = room_id!("!r0");
811 let room_id_1 = room_id!("!r1");
812 let thread_id_0_0 = event_id!("$ev0.0");
813
814 let server = MatrixMockServer::new().await;
815 let client = server.client_builder().build().await;
816
817 client.base_client().get_or_create_room(room_id_0, RoomState::Joined);
818 client.base_client().get_or_create_room(room_id_1, RoomState::Joined);
819
820 client.event_cache().subscribe().unwrap();
821
822 let latest_events = client.latest_events().await;
823
824 assert!(latest_events.listen_to_thread(room_id_0, thread_id_0_0).await.unwrap());
826
827 {
828 let rooms = latest_events.state.registered_rooms.rooms.read().await;
829 assert_eq!(rooms.len(), 1);
831 assert!(rooms.contains_key(room_id_0));
833
834 let room_0 = rooms.get(room_id_0).unwrap().read().await;
836 assert_eq!(room_0.per_thread().len(), 1);
837 assert!(room_0.per_thread().contains_key(thread_id_0_0));
839 }
840
841 latest_events.forget_thread(room_id_0, thread_id_0_0).await;
843
844 {
845 let rooms = latest_events.state.registered_rooms.rooms.read().await;
846 assert_eq!(rooms.len(), 1);
848 assert!(rooms.contains_key(room_id_0));
850
851 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
853 }
854 }
855
856 #[async_test]
857 async fn test_inputs_task_can_listen_to_room_event_cache() {
858 let room_id = owned_room_id!("!r0");
859
860 let server = MatrixMockServer::new().await;
861 let client = server.client_builder().build().await;
862 let weak_client = WeakClient::from_client(&client);
863 let weak_room = WeakRoom::new(weak_client, room_id.clone());
864
865 let event_cache = client.event_cache();
866
867 let registered_rooms = RwLock::new(HashMap::new());
868 let (room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
869 broadcast::channel(1);
870 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
871 broadcast::channel(1);
872 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
873 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
874
875 {
877 room_event_cache_generic_update_sender
878 .send(RoomEventCacheGenericUpdate { room_id: room_id.clone() })
879 .unwrap();
880
881 assert!(
883 listen_to_updates(
884 ®istered_rooms,
885 &mut room_event_cache_generic_update_receiver,
886 &mut send_queue_generic_update_receiver,
887 &mut room_info_update_receiver,
888 &latest_event_queue_sender,
889 )
890 .await
891 .is_continue()
892 );
893
894 assert!(latest_event_queue_receiver.is_empty());
896 }
897
898 {
901 registered_rooms.write().await.insert(
902 room_id.clone(),
903 With::inner(RoomLatestEvents::new(weak_room, event_cache)),
904 );
905 room_event_cache_generic_update_sender
906 .send(RoomEventCacheGenericUpdate { room_id: room_id.clone() })
907 .unwrap();
908
909 assert!(
910 listen_to_updates(
911 ®istered_rooms,
912 &mut room_event_cache_generic_update_receiver,
913 &mut send_queue_generic_update_receiver,
914 &mut room_info_update_receiver,
915 &latest_event_queue_sender,
916 )
917 .await
918 .is_continue()
919 );
920
921 assert!(latest_event_queue_receiver.is_empty().not());
923 }
924 }
925
926 #[async_test]
927 async fn test_inputs_task_can_listen_to_send_queue() {
928 let room_id = owned_room_id!("!r0");
929
930 let server = MatrixMockServer::new().await;
931 let client = server.client_builder().build().await;
932 let weak_client = WeakClient::from_client(&client);
933 let weak_room = WeakRoom::new(weak_client, room_id.clone());
934
935 let event_cache = client.event_cache();
936
937 let registered_rooms = RwLock::new(HashMap::new());
938
939 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
940 broadcast::channel(1);
941 let (send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
942 broadcast::channel(1);
943 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
944 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
945
946 {
948 send_queue_generic_update_sender
949 .send(SendQueueUpdate {
950 room_id: room_id.clone(),
951 update: RoomSendQueueUpdate::SentEvent {
952 transaction_id: OwnedTransactionId::from("txnid0"),
953 event_id: owned_event_id!("$ev0"),
954 },
955 })
956 .unwrap();
957
958 assert!(
960 listen_to_updates(
961 ®istered_rooms,
962 &mut room_event_cache_generic_update_receiver,
963 &mut send_queue_generic_update_receiver,
964 &mut room_info_update_receiver,
965 &latest_event_queue_sender,
966 )
967 .await
968 .is_continue()
969 );
970
971 assert!(latest_event_queue_receiver.is_empty());
973 }
974
975 {
978 registered_rooms.write().await.insert(
979 room_id.clone(),
980 With::inner(RoomLatestEvents::new(weak_room, event_cache)),
981 );
982 send_queue_generic_update_sender
983 .send(SendQueueUpdate {
984 room_id: room_id.clone(),
985 update: RoomSendQueueUpdate::SentEvent {
986 transaction_id: OwnedTransactionId::from("txnid1"),
987 event_id: owned_event_id!("$ev1"),
988 },
989 })
990 .unwrap();
991
992 assert!(
993 listen_to_updates(
994 ®istered_rooms,
995 &mut room_event_cache_generic_update_receiver,
996 &mut send_queue_generic_update_receiver,
997 &mut room_info_update_receiver,
998 &latest_event_queue_sender,
999 )
1000 .await
1001 .is_continue()
1002 );
1003
1004 assert!(latest_event_queue_receiver.is_empty().not());
1006 }
1007 }
1008
1009 #[async_test]
1010 async fn test_inputs_task_can_listen_to_room_info() {
1011 let room_id = owned_room_id!("!r0");
1012
1013 let server = MatrixMockServer::new().await;
1014 let client = server.client_builder().build().await;
1015 let weak_client = WeakClient::from_client(&client);
1016 let weak_room = WeakRoom::new(weak_client, room_id.clone());
1017
1018 let event_cache = client.event_cache();
1019
1020 let registered_rooms = RwLock::new(HashMap::new());
1021
1022 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1023 broadcast::channel(1);
1024 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1025 broadcast::channel(1);
1026 let (room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1027 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1028
1029 {
1031 room_info_update_sender
1032 .send(RoomInfoNotableUpdate {
1033 room_id: room_id.clone(),
1034 reasons: RoomInfoNotableUpdateReasons::MEMBERSHIP,
1035 })
1036 .unwrap();
1037
1038 assert!(
1040 listen_to_updates(
1041 ®istered_rooms,
1042 &mut room_event_cache_generic_update_receiver,
1043 &mut send_queue_generic_update_receiver,
1044 &mut room_info_update_receiver,
1045 &latest_event_queue_sender,
1046 )
1047 .await
1048 .is_continue()
1049 );
1050
1051 assert!(latest_event_queue_receiver.is_empty());
1053 }
1054
1055 {
1058 registered_rooms.write().await.insert(
1059 room_id.clone(),
1060 With::inner(RoomLatestEvents::new(weak_room, event_cache)),
1061 );
1062 room_info_update_sender
1063 .send(RoomInfoNotableUpdate {
1064 room_id: room_id.clone(),
1065 reasons: RoomInfoNotableUpdateReasons::MEMBERSHIP,
1066 })
1067 .unwrap();
1068
1069 assert!(
1070 listen_to_updates(
1071 ®istered_rooms,
1072 &mut room_event_cache_generic_update_receiver,
1073 &mut send_queue_generic_update_receiver,
1074 &mut room_info_update_receiver,
1075 &latest_event_queue_sender,
1076 )
1077 .await
1078 .is_continue()
1079 );
1080
1081 assert!(latest_event_queue_receiver.is_empty().not());
1083 }
1084 }
1085
1086 #[async_test]
1087 async fn test_inputs_task_can_listen_to_specific_room_info_update_reasons() {
1088 let room_id = owned_room_id!("!r0");
1089
1090 let server = MatrixMockServer::new().await;
1091 let client = server.client_builder().build().await;
1092 let weak_client = WeakClient::from_client(&client);
1093 let weak_room = WeakRoom::new(weak_client, room_id.clone());
1094
1095 let event_cache = client.event_cache();
1096
1097 let registered_rooms = RwLock::new(HashMap::new());
1098
1099 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1100 broadcast::channel(1);
1101 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1102 broadcast::channel(1);
1103 let (room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1104 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1105
1106 registered_rooms
1107 .write()
1108 .await
1109 .insert(room_id.clone(), With::inner(RoomLatestEvents::new(weak_room, event_cache)));
1110
1111 for reason in {
1116 let mut all = RoomInfoNotableUpdateReasons::all();
1117 all.remove(RoomInfoNotableUpdateReasons::MEMBERSHIP);
1118
1119 all.iter()
1120 } {
1121 room_info_update_sender
1122 .send(RoomInfoNotableUpdate { room_id: room_id.clone(), reasons: reason })
1123 .unwrap();
1124
1125 assert!(
1126 listen_to_updates(
1127 ®istered_rooms,
1128 &mut room_event_cache_generic_update_receiver,
1129 &mut send_queue_generic_update_receiver,
1130 &mut room_info_update_receiver,
1131 &latest_event_queue_sender,
1132 )
1133 .await
1134 .is_continue()
1135 );
1136
1137 assert!(latest_event_queue_receiver.is_empty());
1139 }
1140
1141 {
1143 room_info_update_sender
1144 .send(RoomInfoNotableUpdate {
1145 room_id: room_id.clone(),
1146 reasons: RoomInfoNotableUpdateReasons::MEMBERSHIP,
1147 })
1148 .unwrap();
1149
1150 assert!(
1151 listen_to_updates(
1152 ®istered_rooms,
1153 &mut room_event_cache_generic_update_receiver,
1154 &mut send_queue_generic_update_receiver,
1155 &mut room_info_update_receiver,
1156 &latest_event_queue_sender,
1157 )
1158 .await
1159 .is_continue()
1160 );
1161
1162 assert!(latest_event_queue_receiver.is_empty().not());
1164 }
1165 }
1166
1167 #[async_test]
1168 async fn test_inputs_task_stops_when_event_cache_channel_is_closed() {
1169 let registered_rooms = RwLock::new(HashMap::new());
1170 let (room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1171 broadcast::channel(1);
1172 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1173 broadcast::channel(1);
1174 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1175 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1176
1177 drop(room_event_cache_generic_update_sender);
1179
1180 assert!(
1182 listen_to_updates(
1183 ®istered_rooms,
1184 &mut room_event_cache_generic_update_receiver,
1185 &mut send_queue_generic_update_receiver,
1186 &mut room_info_update_receiver,
1187 &latest_event_queue_sender,
1188 )
1189 .await
1190 .is_break()
1192 );
1193
1194 assert!(latest_event_queue_receiver.is_empty());
1195 }
1196
1197 #[async_test]
1198 async fn test_inputs_task_stops_when_send_queue_channel_is_closed() {
1199 let registered_rooms = RwLock::new(HashMap::new());
1200 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1201 broadcast::channel(1);
1202 let (send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1203 broadcast::channel(1);
1204 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1205 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1206
1207 drop(send_queue_generic_update_sender);
1209
1210 assert!(
1212 listen_to_updates(
1213 ®istered_rooms,
1214 &mut room_event_cache_generic_update_receiver,
1215 &mut send_queue_generic_update_receiver,
1216 &mut room_info_update_receiver,
1217 &latest_event_queue_sender,
1218 )
1219 .await
1220 .is_break()
1222 );
1223
1224 assert!(latest_event_queue_receiver.is_empty());
1225 }
1226
1227 #[async_test]
1228 async fn test_inputs_task_stops_when_room_info_updates_are_closed() {
1229 let registered_rooms = RwLock::new(HashMap::new());
1230 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1231 broadcast::channel(1);
1232 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1233 broadcast::channel(1);
1234 let (room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1235 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1236
1237 drop(room_info_update_sender);
1239
1240 assert!(
1242 listen_to_updates(
1243 ®istered_rooms,
1244 &mut room_event_cache_generic_update_receiver,
1245 &mut send_queue_generic_update_receiver,
1246 &mut room_info_update_receiver,
1247 &latest_event_queue_sender,
1248 )
1249 .await
1250 .is_break()
1252 );
1253
1254 assert!(latest_event_queue_receiver.is_empty());
1255 }
1256
1257 #[async_test]
1258 async fn test_latest_event_value_is_updated_via_event_cache() {
1259 let room_id = owned_room_id!("!r0");
1260 let user_id = user_id!("@mnt_io:matrix.org");
1261 let event_factory = EventFactory::new().sender(user_id).room(&room_id);
1262 let event_id_0 = event_id!("$ev0");
1263
1264 let server = MatrixMockServer::new().await;
1265 let client = server.client_builder().build().await;
1266
1267 client.base_client().get_or_create_room(&room_id, RoomState::Joined);
1269
1270 let event_cache = client.event_cache();
1271 event_cache.subscribe().unwrap();
1272
1273 let latest_events = client.latest_events().await;
1274
1275 let mut latest_event_stream =
1277 latest_events.listen_and_subscribe_to_room(&room_id).await.unwrap().unwrap();
1278
1279 assert_pending!(latest_event_stream);
1281
1282 server
1284 .sync_room(
1285 &client,
1286 JoinedRoomBuilder::new(&room_id)
1287 .add_timeline_event(event_factory.text_msg("raclette !").event_id(event_id_0)),
1288 )
1289 .await;
1290
1291 assert_matches!(
1296 latest_event_stream.next().await,
1297 Some(LatestEventValue::Remote(RemoteLatestEventValue { kind: TimelineEventKind::PlainText { event }, .. })) => {
1298 assert_matches!(
1299 event.deserialize().unwrap(),
1300 AnySyncTimelineEvent::MessageLike(
1301 AnySyncMessageLikeEvent::RoomMessage(
1302 SyncMessageLikeEvent::Original(message_content)
1303 )
1304 ) => {
1305 assert_eq!(message_content.content.body(), "raclette !");
1306 }
1307 );
1308 }
1309 );
1310
1311 assert_pending!(latest_event_stream);
1312 }
1313
1314 #[async_test]
1315 async fn test_latest_event_value_is_initialized_by_the_event_cache_lazily() {
1316 let room_id = owned_room_id!("!r0");
1317 let user_id = user_id!("@mnt_io:matrix.org");
1318 let event_factory = EventFactory::new().sender(user_id).room(&room_id);
1319 let event_id_0 = event_id!("$ev0");
1320
1321 let server = MatrixMockServer::new().await;
1322 let client = server.client_builder().build().await;
1323
1324 {
1326 client.base_client().get_or_create_room(&room_id, RoomState::Joined);
1328
1329 client
1331 .event_cache_store()
1332 .lock()
1333 .await
1334 .expect("Could not acquire the event cache lock")
1335 .as_clean()
1336 .expect("Could not acquire a clean event cache lock")
1337 .handle_linked_chunk_updates(
1338 LinkedChunkId::Room(&room_id),
1339 vec![
1340 Update::NewItemsChunk {
1341 previous: None,
1342 new: ChunkIdentifier::new(0),
1343 next: None,
1344 },
1345 Update::PushItems {
1346 at: Position::new(ChunkIdentifier::new(0), 0),
1347 items: vec![
1348 event_factory.text_msg("hello").event_id(event_id_0).into(),
1349 ],
1350 },
1351 ],
1352 )
1353 .await
1354 .unwrap();
1355 }
1356
1357 let event_cache = client.event_cache();
1358 event_cache.subscribe().unwrap();
1359
1360 let latest_events = client.latest_events().await;
1361
1362 let mut latest_event_stream =
1363 latest_events.listen_and_subscribe_to_room(&room_id).await.unwrap().unwrap();
1364
1365 yield_now().await;
1371 assert_matches!(latest_event_stream.next_now().await, LatestEventValue::Remote(_));
1372
1373 assert_pending!(latest_event_stream);
1374 }
1375
1376 #[async_test]
1384 async fn test_latest_event_value_is_initialized_by_the_event_cache_lazily_inner() {
1385 let room_id_0 = owned_room_id!("!r0");
1386 let room_id_1 = owned_room_id!("!r1");
1387
1388 let server = MatrixMockServer::new().await;
1389 let client = server.client_builder().build().await;
1390
1391 let room_0 = client.base_client().get_or_create_room(&room_id_0, RoomState::Joined);
1393 let room_1 = client.base_client().get_or_create_room(&room_id_1, RoomState::Joined);
1394
1395 let mut room_info_1 = room_0.clone_info();
1398 room_info_1.set_latest_event(LatestEventValue::LocalIsSending(local_room_message("foo")));
1399 room_1.update_room_info(|_| (room_info_1, Default::default())).await;
1400
1401 let weak_client = WeakClient::from_client(&client);
1402
1403 let event_cache = client.event_cache();
1404 event_cache.subscribe().unwrap();
1405
1406 let (latest_event_queue_sender, mut latest_event_queue_receiver) =
1407 mpsc::unbounded_channel();
1408
1409 let registered_rooms =
1410 RegisteredRooms::new(weak_client, event_cache, &latest_event_queue_sender);
1411
1412 {
1415 let room_latest_events = registered_rooms.for_room(&room_id_0).await.unwrap().unwrap();
1416 assert_matches!(
1417 room_latest_events.read().await.for_room().get().await,
1418 LatestEventValue::None
1419 );
1420 assert_matches!(
1421 latest_event_queue_receiver.recv().await,
1422 Some(LatestEventQueueUpdate::EventCache { room_id }) => {
1423 assert_eq!(room_id, room_id_0);
1424 }
1425 );
1426 assert!(latest_event_queue_receiver.is_empty());
1427 }
1428
1429 {
1432 let room_latest_events = registered_rooms.for_room(&room_id_1).await.unwrap().unwrap();
1433 assert_matches!(
1434 room_latest_events.read().await.for_room().get().await,
1435 LatestEventValue::LocalIsSending(_)
1436 );
1437 assert!(latest_event_queue_receiver.is_empty());
1438 }
1439 }
1440
1441 #[async_test]
1442 async fn test_latest_event_value_is_updated_via_room_infos_for_invites() {
1443 let room_id = owned_room_id!("!r0");
1444 let event_factory = EventFactory::new().room(&room_id);
1445 let event_id_0 = event_id!("$ev0");
1446 let event_id_1 = event_id!("$ev1");
1447
1448 let server = MatrixMockServer::new().await;
1449 let client = server.client_builder().build().await;
1450 let own_user_id = client.user_id().unwrap();
1451 let other_user_id = user_id!("@other:servername");
1452
1453 let event_cache = client.event_cache();
1454 event_cache.subscribe().unwrap();
1455
1456 let latest_events = client.latest_events().await;
1457
1458 let mut latest_event_stream =
1460 latest_events.listen_and_subscribe_to_room(&room_id).await.unwrap().unwrap();
1461
1462 assert_pending!(latest_event_stream);
1464
1465 let now = MilliSecondsSinceUnixEpoch::now().get();
1466
1467 {
1469 server
1470 .sync_room(
1471 &client,
1472 InvitedRoomBuilder::new(&room_id).add_state_event(
1473 event_factory
1474 .member(other_user_id)
1475 .invited(own_user_id)
1476 .event_id(event_id_0),
1477 ),
1478 )
1479 .await;
1480
1481 assert_matches!(
1486 latest_event_stream.next().await,
1487 Some(LatestEventValue::RemoteInvite { event_id, timestamp, inviter }) => {
1488 assert!(event_id.is_none());
1490 assert!(timestamp.get() >= now);
1492 assert_eq!(inviter.as_deref(), Some(other_user_id));
1493 }
1494 );
1495
1496 assert_pending!(latest_event_stream);
1497 };
1498
1499 {
1501 server
1502 .sync_room(
1503 &client,
1504 InvitedRoomBuilder::new(&room_id).add_state_event(
1505 event_factory
1506 .member(other_user_id)
1507 .invited(own_user_id)
1508 .event_id(event_id_0),
1509 ),
1510 )
1511 .await;
1512
1513 assert!(timeout(Duration::from_secs(1), latest_event_stream.next()).await.is_err());
1519
1520 assert_pending!(latest_event_stream);
1521 }
1522
1523 {
1525 let now = u64::from(now) + 10; server
1527 .sync_room(
1528 &client,
1529 JoinedRoomBuilder::new(&room_id).add_timeline_event(
1530 event_factory
1531 .member(own_user_id)
1532 .membership(MembershipState::Join)
1533 .event_id(event_id_1)
1534 .server_ts(now),
1535 ),
1536 )
1537 .await;
1538
1539 assert_matches!(
1544 latest_event_stream.next().await,
1545 Some(LatestEventValue::Remote(RemoteLatestEventValue { kind: TimelineEventKind::PlainText { event }, .. })) => {
1546 assert_matches!(
1547 event.deserialize().unwrap(),
1548 AnySyncTimelineEvent::State(
1549 AnySyncStateEvent::RoomMember(
1550 SyncRoomMemberEvent::Original(event)
1551 )
1552 ) => {
1553 assert_eq!(event.event_id, event_id_1);
1554 assert_eq!(event.content.membership, MembershipState::Join);
1555 assert_eq!(event.sender, own_user_id);
1556 assert_eq!(event.state_key, own_user_id);
1557 assert_eq!(u64::from(event.origin_server_ts.get()), now);
1558 }
1559 );
1560 }
1561 );
1562
1563 assert_pending!(latest_event_stream);
1564 }
1565 }
1566}