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 {
297 let _ = latest_event_queue_sender
298 .send(LatestEventQueueUpdate::EventCache { room_id: room_id.to_owned() });
299 }
300 }
301
302 Ok(match thread_id {
303 Some(thread_id) => {
309 let mut rooms = self.rooms.write().await;
310
311 if rooms.contains_key(room_id).not() {
313 create_and_insert_room_latest_events(
314 room_id,
315 rooms.deref_mut(),
316 &self.weak_client,
317 &self.event_cache,
318 &self.latest_event_queue_sender,
319 );
320 }
321
322 if let Some(room_latest_event) = rooms.get(room_id) {
323 let mut room_latest_event = room_latest_event.write().await;
324
325 if room_latest_event.has_thread(thread_id).not() {
328 room_latest_event.create_and_insert_latest_event_for_thread(thread_id);
329 }
330 }
331
332 RwLockWriteGuard::try_downgrade_map(rooms, |rooms| rooms.get(room_id)).ok()
333 }
334
335 None => {
338 match RwLockReadGuard::try_map(self.rooms.read().await, |rooms| rooms.get(room_id))
339 .ok()
340 {
341 value @ Some(_) => value,
342 None => {
343 let _timer = timer!(
344 tracing::Level::INFO,
345 format!("Creating `RoomLatestEvents` for {room_id:?}"),
346 );
347
348 let mut rooms = self.rooms.write().await;
349
350 if rooms.contains_key(room_id).not() {
351 create_and_insert_room_latest_events(
352 room_id,
353 rooms.deref_mut(),
354 &self.weak_client,
355 &self.event_cache,
356 &self.latest_event_queue_sender,
357 );
358 }
359
360 RwLockWriteGuard::try_downgrade_map(rooms, |rooms| rooms.get(room_id)).ok()
361 }
362 }
363 }
364 })
365 }
366
367 pub async fn for_room(
371 &self,
372 room_id: &RoomId,
373 ) -> Result<Option<RwLockReadGuard<'_, RoomLatestEvents>>, LatestEventsError> {
374 self.room_latest_event(room_id, None).await
375 }
376
377 pub async fn for_thread(
381 &self,
382 room_id: &RoomId,
383 thread_id: &EventId,
384 ) -> Result<Option<RwLockReadGuard<'_, RoomLatestEvents>>, LatestEventsError> {
385 self.room_latest_event(room_id, Some(thread_id)).await
386 }
387
388 pub async fn forget_room(&self, room_id: &RoomId) {
395 {
396 let mut rooms = self.rooms.write().await;
397
398 rooms.remove(room_id);
400 }
401 }
402
403 pub async fn forget_thread(&self, room_id: &RoomId, thread_id: &EventId) {
411 let rooms = self.rooms.read().await;
412
413 if let Some(room_latest_event) = rooms.get(room_id) {
415 let mut room_latest_event = room_latest_event.write().await;
416
417 drop(rooms);
419
420 room_latest_event.forget_thread(thread_id);
421 }
422 }
423}
424
425#[derive(Debug)]
428enum LatestEventQueueUpdate {
429 EventCache {
431 room_id: OwnedRoomId,
433 },
434
435 SendQueue {
437 room_id: OwnedRoomId,
439
440 update: RoomSendQueueUpdate,
442 },
443
444 RoomInfo {
448 room_id: OwnedRoomId,
450
451 reasons: RoomInfoNotableUpdateReasons,
453 },
454}
455
456async fn listen_to_updates_task(
465 registered_rooms: Arc<RegisteredRooms>,
466 event_cache: EventCache,
467 send_queue: SendQueue,
468 room_info_updates: broadcast::Receiver<RoomInfoNotableUpdate>,
469 latest_event_queue_sender: mpsc::UnboundedSender<LatestEventQueueUpdate>,
470) {
471 let mut event_cache_generic_updates_subscriber =
472 event_cache.subscribe_to_room_generic_updates();
473 let mut send_queue_generic_updates_subscriber = send_queue.subscribe();
474 let mut room_info_updates_subscriber = room_info_updates.resubscribe();
475
476 loop {
477 if listen_to_updates(
478 ®istered_rooms.rooms,
479 &mut event_cache_generic_updates_subscriber,
480 &mut send_queue_generic_updates_subscriber,
481 &mut room_info_updates_subscriber,
482 &latest_event_queue_sender,
483 )
484 .await
485 .is_break()
486 {
487 warn!("`listen_to_updates_task` has stopped");
488
489 break;
490 }
491 }
492}
493
494async fn listen_to_updates(
499 registered_rooms: &RwLock<HashMap<OwnedRoomId, RoomLatestEvents>>,
500 event_cache_generic_updates_subscriber: &mut broadcast::Receiver<RoomEventCacheGenericUpdate>,
501 send_queue_generic_updates_subscriber: &mut broadcast::Receiver<SendQueueUpdate>,
502 room_info_updates_subscriber: &mut broadcast::Receiver<RoomInfoNotableUpdate>,
503 latest_event_queue_sender: &mpsc::UnboundedSender<LatestEventQueueUpdate>,
504) -> ControlFlow<()> {
505 select! {
506 room_event_cache_generic_update = event_cache_generic_updates_subscriber.recv() => {
507 if let Ok(RoomEventCacheGenericUpdate { room_id }) = room_event_cache_generic_update {
508 if registered_rooms.read().await.contains_key(&room_id) {
509 let _ = latest_event_queue_sender.send(LatestEventQueueUpdate::EventCache {
510 room_id
511 });
512 }
513 } else {
514 warn!("`event_cache_generic_updates` channel has been closed");
515
516 return ControlFlow::Break(());
517 }
518 }
519
520 send_queue_generic_update = send_queue_generic_updates_subscriber.recv() => {
521 if let Ok(SendQueueUpdate { room_id, update }) = send_queue_generic_update {
522 if registered_rooms.read().await.contains_key(&room_id) {
523 let _ = latest_event_queue_sender.send(LatestEventQueueUpdate::SendQueue {
524 room_id,
525 update
526 });
527 }
528 } else {
529 warn!("`send_queue_generic_updates` channel has been closed");
530
531 return ControlFlow::Break(());
532 }
533 }
534
535 room_info_update = room_info_updates_subscriber.recv() => {
536 if let Ok(RoomInfoNotableUpdate { room_id, reasons }) = room_info_update {
537 if
539 reasons == RoomInfoNotableUpdateReasons::LATEST_EVENT ||
542
543 !reasons.contains(RoomInfoNotableUpdateReasons::MEMBERSHIP)
547 {
548 return ControlFlow::Continue(())
549 }
550
551 if registered_rooms.read().await.contains_key(&room_id) {
552 let _ = latest_event_queue_sender.send(LatestEventQueueUpdate::RoomInfo {
553 room_id,
554 reasons,
555 });
556 }
557 } else {
558 warn!("`room_info_updates` channel has been closed");
559
560 return ControlFlow::Break(());
561 }
562 }
563 }
564
565 ControlFlow::Continue(())
566}
567
568async fn compute_latest_events_task(
573 registered_rooms: Arc<RegisteredRooms>,
574 mut latest_event_queue_receiver: mpsc::UnboundedReceiver<LatestEventQueueUpdate>,
575) {
576 const BUFFER_SIZE: usize = 16;
577
578 let mut buffer = Vec::with_capacity(BUFFER_SIZE);
579
580 while latest_event_queue_receiver.recv_many(&mut buffer, BUFFER_SIZE).await > 0 {
581 compute_latest_events(®istered_rooms, &buffer).await;
582 buffer.clear();
583 }
584
585 warn!("`compute_latest_events_task` has stopped");
586}
587
588async fn compute_latest_events(
589 registered_rooms: &RegisteredRooms,
590 latest_event_queue_updates: &[LatestEventQueueUpdate],
591) {
592 async fn room_latest_events_write_guard(
593 registered_rooms: &RegisteredRooms,
594 room_id: &OwnedRoomId,
595 ) -> ControlFlow<RoomLatestEventsWriteGuard, ()> {
596 let rooms = registered_rooms.rooms.read().await;
597
598 if let Some(room_latest_events) = rooms.get(room_id) {
599 let room_latest_events = room_latest_events.write().await;
600
601 drop(rooms);
604
605 ControlFlow::Break(room_latest_events)
606 } else {
607 info!(?room_id, "Failed to find the room");
608
609 ControlFlow::Continue(())
610 }
611 }
612
613 for latest_event_queue_update in latest_event_queue_updates {
614 match latest_event_queue_update {
615 LatestEventQueueUpdate::EventCache { room_id } => {
616 let ControlFlow::Break(mut room_latest_events) =
617 room_latest_events_write_guard(registered_rooms, room_id).await
618 else {
619 continue;
620 };
621
622 room_latest_events.update_with_event_cache().await;
623 }
624
625 LatestEventQueueUpdate::SendQueue { room_id, update } => {
626 let ControlFlow::Break(mut room_latest_events) =
627 room_latest_events_write_guard(registered_rooms, room_id).await
628 else {
629 continue;
630 };
631
632 room_latest_events.update_with_send_queue(update).await;
633 }
634
635 LatestEventQueueUpdate::RoomInfo { room_id, reasons } => {
636 let ControlFlow::Break(mut room_latest_events) =
637 room_latest_events_write_guard(registered_rooms, room_id).await
638 else {
639 continue;
640 };
641
642 room_latest_events.update_with_room_info(*reasons).await;
643 }
644 }
645 }
646}
647
648#[cfg(test)]
649fn local_room_message(body: &str) -> LocalLatestEventValue {
650 use matrix_sdk_base::store::SerializableEventContent;
651 use ruma::{
652 MilliSecondsSinceUnixEpoch,
653 events::{AnyMessageLikeEventContent, room::message::RoomMessageEventContent},
654 };
655
656 LocalLatestEventValue {
657 timestamp: MilliSecondsSinceUnixEpoch::now(),
658 content: SerializableEventContent::new(&AnyMessageLikeEventContent::RoomMessage(
659 RoomMessageEventContent::text_plain(body),
660 ))
661 .unwrap(),
662 }
663}
664
665#[cfg(all(test, not(target_family = "wasm")))]
666mod tests {
667 use std::{collections::HashMap, ops::Not, time::Duration};
668
669 use assert_matches::assert_matches;
670 use matrix_sdk_base::{
671 RoomState,
672 deserialized_responses::TimelineEventKind,
673 linked_chunk::{ChunkIdentifier, LinkedChunkId, Position, Update},
674 };
675 use matrix_sdk_test::{
676 InvitedRoomBuilder, JoinedRoomBuilder, async_test, event_factory::EventFactory,
677 };
678 use ruma::{
679 MilliSecondsSinceUnixEpoch, OwnedTransactionId, event_id,
680 events::{
681 AnySyncMessageLikeEvent, AnySyncStateEvent, AnySyncTimelineEvent, SyncMessageLikeEvent,
682 room::member::{MembershipState, SyncRoomMemberEvent},
683 },
684 owned_event_id, owned_room_id, room_id, user_id,
685 };
686 use stream_assert::assert_pending;
687 use tokio::{task::yield_now, time::timeout};
688
689 use super::{
690 LatestEventValue, RegisteredRooms, RemoteLatestEventValue, RoomEventCacheGenericUpdate,
691 RoomInfoNotableUpdate, RoomInfoNotableUpdateReasons, RoomLatestEvents, RoomSendQueueUpdate,
692 RwLock, SendQueueUpdate, WeakClient, WeakRoom, With, broadcast, listen_to_updates, mpsc,
693 };
694 use crate::{
695 latest_events::{LatestEventQueueUpdate, local_room_message},
696 test_utils::mocks::MatrixMockServer,
697 };
698
699 #[async_test]
700 async fn test_latest_events_are_lazy() {
701 let room_id_0 = room_id!("!r0");
702 let room_id_1 = room_id!("!r1");
703 let room_id_2 = room_id!("!r2");
704 let thread_id_1_0 = event_id!("$ev1.0");
705 let thread_id_2_0 = event_id!("$ev2.0");
706
707 let server = MatrixMockServer::new().await;
708 let client = server.client_builder().build().await;
709
710 client.base_client().get_or_create_room(room_id_0, RoomState::Joined);
711 client.base_client().get_or_create_room(room_id_1, RoomState::Joined);
712 client.base_client().get_or_create_room(room_id_2, RoomState::Joined);
713
714 client.event_cache().subscribe().unwrap();
715
716 let latest_events = client.latest_events().await;
717
718 assert!(latest_events.state.registered_rooms.rooms.read().await.is_empty());
720
721 assert!(latest_events.listen_to_room(room_id_0).await.unwrap());
723 assert!(latest_events.listen_to_room(room_id_1).await.unwrap());
724
725 {
726 let rooms = latest_events.state.registered_rooms.rooms.read().await;
727 assert_eq!(rooms.len(), 2);
729 assert!(rooms.contains_key(room_id_0));
731 assert!(rooms.contains_key(room_id_1));
732
733 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
735 assert!(rooms.get(room_id_1).unwrap().read().await.per_thread().is_empty());
737 }
738
739 assert!(latest_events.listen_to_thread(room_id_1, thread_id_1_0).await.unwrap());
741 assert!(latest_events.listen_to_thread(room_id_2, thread_id_2_0).await.unwrap());
742
743 {
744 let rooms = latest_events.state.registered_rooms.rooms.read().await;
745 assert_eq!(rooms.len(), 3);
747 assert!(rooms.contains_key(room_id_0));
749 assert!(rooms.contains_key(room_id_1));
750 assert!(rooms.contains_key(room_id_2));
751
752 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
754 let room_1 = rooms.get(room_id_1).unwrap().read().await;
756 assert_eq!(room_1.per_thread().len(), 1);
757 assert!(room_1.per_thread().contains_key(thread_id_1_0));
759 let room_2 = rooms.get(room_id_2).unwrap().read().await;
761 assert_eq!(room_2.per_thread().len(), 1);
762 assert!(room_2.per_thread().contains_key(thread_id_2_0));
764 }
765 }
766
767 #[async_test]
768 async fn test_forget_room() {
769 let room_id_0 = room_id!("!r0");
770 let room_id_1 = room_id!("!r1");
771
772 let server = MatrixMockServer::new().await;
773 let client = server.client_builder().build().await;
774
775 client.base_client().get_or_create_room(room_id_0, RoomState::Joined);
776 client.base_client().get_or_create_room(room_id_1, RoomState::Joined);
777
778 client.event_cache().subscribe().unwrap();
779
780 let latest_events = client.latest_events().await;
781
782 assert!(latest_events.listen_to_room(room_id_0).await.unwrap());
784
785 {
786 let rooms = latest_events.state.registered_rooms.rooms.read().await;
787 assert_eq!(rooms.len(), 1);
789 assert!(rooms.contains_key(room_id_0));
791
792 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
794 }
795
796 latest_events.forget_room(room_id_0).await;
798
799 {
800 let rooms = latest_events.state.registered_rooms.rooms.read().await;
801 assert!(rooms.is_empty());
803 }
804 }
805
806 #[async_test]
807 async fn test_forget_thread() {
808 let room_id_0 = room_id!("!r0");
809 let room_id_1 = room_id!("!r1");
810 let thread_id_0_0 = event_id!("$ev0.0");
811
812 let server = MatrixMockServer::new().await;
813 let client = server.client_builder().build().await;
814
815 client.base_client().get_or_create_room(room_id_0, RoomState::Joined);
816 client.base_client().get_or_create_room(room_id_1, RoomState::Joined);
817
818 client.event_cache().subscribe().unwrap();
819
820 let latest_events = client.latest_events().await;
821
822 assert!(latest_events.listen_to_thread(room_id_0, thread_id_0_0).await.unwrap());
824
825 {
826 let rooms = latest_events.state.registered_rooms.rooms.read().await;
827 assert_eq!(rooms.len(), 1);
829 assert!(rooms.contains_key(room_id_0));
831
832 let room_0 = rooms.get(room_id_0).unwrap().read().await;
834 assert_eq!(room_0.per_thread().len(), 1);
835 assert!(room_0.per_thread().contains_key(thread_id_0_0));
837 }
838
839 latest_events.forget_thread(room_id_0, thread_id_0_0).await;
841
842 {
843 let rooms = latest_events.state.registered_rooms.rooms.read().await;
844 assert_eq!(rooms.len(), 1);
846 assert!(rooms.contains_key(room_id_0));
848
849 assert!(rooms.get(room_id_0).unwrap().read().await.per_thread().is_empty());
851 }
852 }
853
854 #[async_test]
855 async fn test_inputs_task_can_listen_to_room_event_cache() {
856 let room_id = owned_room_id!("!r0");
857
858 let server = MatrixMockServer::new().await;
859 let client = server.client_builder().build().await;
860 let weak_client = WeakClient::from_client(&client);
861 let weak_room = WeakRoom::new(weak_client, room_id.clone());
862
863 let event_cache = client.event_cache();
864
865 let registered_rooms = RwLock::new(HashMap::new());
866 let (room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
867 broadcast::channel(1);
868 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
869 broadcast::channel(1);
870 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
871 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
872
873 {
875 room_event_cache_generic_update_sender
876 .send(RoomEventCacheGenericUpdate { room_id: room_id.clone() })
877 .unwrap();
878
879 assert!(
881 listen_to_updates(
882 ®istered_rooms,
883 &mut room_event_cache_generic_update_receiver,
884 &mut send_queue_generic_update_receiver,
885 &mut room_info_update_receiver,
886 &latest_event_queue_sender,
887 )
888 .await
889 .is_continue()
890 );
891
892 assert!(latest_event_queue_receiver.is_empty());
894 }
895
896 {
898 registered_rooms.write().await.insert(
899 room_id.clone(),
900 With::inner(RoomLatestEvents::new(weak_room, event_cache)),
901 );
902 room_event_cache_generic_update_sender
903 .send(RoomEventCacheGenericUpdate { room_id: room_id.clone() })
904 .unwrap();
905
906 assert!(
907 listen_to_updates(
908 ®istered_rooms,
909 &mut room_event_cache_generic_update_receiver,
910 &mut send_queue_generic_update_receiver,
911 &mut room_info_update_receiver,
912 &latest_event_queue_sender,
913 )
914 .await
915 .is_continue()
916 );
917
918 assert!(latest_event_queue_receiver.is_empty().not());
920 }
921 }
922
923 #[async_test]
924 async fn test_inputs_task_can_listen_to_send_queue() {
925 let room_id = owned_room_id!("!r0");
926
927 let server = MatrixMockServer::new().await;
928 let client = server.client_builder().build().await;
929 let weak_client = WeakClient::from_client(&client);
930 let weak_room = WeakRoom::new(weak_client, room_id.clone());
931
932 let event_cache = client.event_cache();
933
934 let registered_rooms = RwLock::new(HashMap::new());
935
936 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
937 broadcast::channel(1);
938 let (send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
939 broadcast::channel(1);
940 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
941 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
942
943 {
945 send_queue_generic_update_sender
946 .send(SendQueueUpdate {
947 room_id: room_id.clone(),
948 update: RoomSendQueueUpdate::SentEvent {
949 transaction_id: OwnedTransactionId::from("txnid0"),
950 event_id: owned_event_id!("$ev0"),
951 },
952 })
953 .unwrap();
954
955 assert!(
957 listen_to_updates(
958 ®istered_rooms,
959 &mut room_event_cache_generic_update_receiver,
960 &mut send_queue_generic_update_receiver,
961 &mut room_info_update_receiver,
962 &latest_event_queue_sender,
963 )
964 .await
965 .is_continue()
966 );
967
968 assert!(latest_event_queue_receiver.is_empty());
970 }
971
972 {
974 registered_rooms.write().await.insert(
975 room_id.clone(),
976 With::inner(RoomLatestEvents::new(weak_room, event_cache)),
977 );
978 send_queue_generic_update_sender
979 .send(SendQueueUpdate {
980 room_id: room_id.clone(),
981 update: RoomSendQueueUpdate::SentEvent {
982 transaction_id: OwnedTransactionId::from("txnid1"),
983 event_id: owned_event_id!("$ev1"),
984 },
985 })
986 .unwrap();
987
988 assert!(
989 listen_to_updates(
990 ®istered_rooms,
991 &mut room_event_cache_generic_update_receiver,
992 &mut send_queue_generic_update_receiver,
993 &mut room_info_update_receiver,
994 &latest_event_queue_sender,
995 )
996 .await
997 .is_continue()
998 );
999
1000 assert!(latest_event_queue_receiver.is_empty().not());
1002 }
1003 }
1004
1005 #[async_test]
1006 async fn test_inputs_task_can_listen_to_room_info() {
1007 let room_id = owned_room_id!("!r0");
1008
1009 let server = MatrixMockServer::new().await;
1010 let client = server.client_builder().build().await;
1011 let weak_client = WeakClient::from_client(&client);
1012 let weak_room = WeakRoom::new(weak_client, room_id.clone());
1013
1014 let event_cache = client.event_cache();
1015
1016 let registered_rooms = RwLock::new(HashMap::new());
1017
1018 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1019 broadcast::channel(1);
1020 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1021 broadcast::channel(1);
1022 let (room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1023 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1024
1025 {
1027 room_info_update_sender
1028 .send(RoomInfoNotableUpdate {
1029 room_id: room_id.clone(),
1030 reasons: RoomInfoNotableUpdateReasons::MEMBERSHIP,
1031 })
1032 .unwrap();
1033
1034 assert!(
1036 listen_to_updates(
1037 ®istered_rooms,
1038 &mut room_event_cache_generic_update_receiver,
1039 &mut send_queue_generic_update_receiver,
1040 &mut room_info_update_receiver,
1041 &latest_event_queue_sender,
1042 )
1043 .await
1044 .is_continue()
1045 );
1046
1047 assert!(latest_event_queue_receiver.is_empty());
1049 }
1050
1051 {
1053 registered_rooms.write().await.insert(
1054 room_id.clone(),
1055 With::inner(RoomLatestEvents::new(weak_room, event_cache)),
1056 );
1057 room_info_update_sender
1058 .send(RoomInfoNotableUpdate {
1059 room_id: room_id.clone(),
1060 reasons: RoomInfoNotableUpdateReasons::MEMBERSHIP,
1061 })
1062 .unwrap();
1063
1064 assert!(
1065 listen_to_updates(
1066 ®istered_rooms,
1067 &mut room_event_cache_generic_update_receiver,
1068 &mut send_queue_generic_update_receiver,
1069 &mut room_info_update_receiver,
1070 &latest_event_queue_sender,
1071 )
1072 .await
1073 .is_continue()
1074 );
1075
1076 assert!(latest_event_queue_receiver.is_empty().not());
1078 }
1079 }
1080
1081 #[async_test]
1082 async fn test_inputs_task_can_listen_to_specific_room_info_update_reasons() {
1083 let room_id = owned_room_id!("!r0");
1084
1085 let server = MatrixMockServer::new().await;
1086 let client = server.client_builder().build().await;
1087 let weak_client = WeakClient::from_client(&client);
1088 let weak_room = WeakRoom::new(weak_client, room_id.clone());
1089
1090 let event_cache = client.event_cache();
1091
1092 let registered_rooms = RwLock::new(HashMap::new());
1093
1094 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1095 broadcast::channel(1);
1096 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1097 broadcast::channel(1);
1098 let (room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1099 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1100
1101 registered_rooms
1102 .write()
1103 .await
1104 .insert(room_id.clone(), With::inner(RoomLatestEvents::new(weak_room, event_cache)));
1105
1106 for reason in {
1111 let mut all = RoomInfoNotableUpdateReasons::all();
1112 all.remove(RoomInfoNotableUpdateReasons::MEMBERSHIP);
1113
1114 all.iter()
1115 } {
1116 room_info_update_sender
1117 .send(RoomInfoNotableUpdate { room_id: room_id.clone(), reasons: reason })
1118 .unwrap();
1119
1120 assert!(
1121 listen_to_updates(
1122 ®istered_rooms,
1123 &mut room_event_cache_generic_update_receiver,
1124 &mut send_queue_generic_update_receiver,
1125 &mut room_info_update_receiver,
1126 &latest_event_queue_sender,
1127 )
1128 .await
1129 .is_continue()
1130 );
1131
1132 assert!(latest_event_queue_receiver.is_empty());
1134 }
1135
1136 {
1138 room_info_update_sender
1139 .send(RoomInfoNotableUpdate {
1140 room_id: room_id.clone(),
1141 reasons: RoomInfoNotableUpdateReasons::MEMBERSHIP,
1142 })
1143 .unwrap();
1144
1145 assert!(
1146 listen_to_updates(
1147 ®istered_rooms,
1148 &mut room_event_cache_generic_update_receiver,
1149 &mut send_queue_generic_update_receiver,
1150 &mut room_info_update_receiver,
1151 &latest_event_queue_sender,
1152 )
1153 .await
1154 .is_continue()
1155 );
1156
1157 assert!(latest_event_queue_receiver.is_empty().not());
1159 }
1160 }
1161
1162 #[async_test]
1163 async fn test_inputs_task_stops_when_event_cache_channel_is_closed() {
1164 let registered_rooms = RwLock::new(HashMap::new());
1165 let (room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1166 broadcast::channel(1);
1167 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1168 broadcast::channel(1);
1169 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1170 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1171
1172 drop(room_event_cache_generic_update_sender);
1174
1175 assert!(
1177 listen_to_updates(
1178 ®istered_rooms,
1179 &mut room_event_cache_generic_update_receiver,
1180 &mut send_queue_generic_update_receiver,
1181 &mut room_info_update_receiver,
1182 &latest_event_queue_sender,
1183 )
1184 .await
1185 .is_break()
1187 );
1188
1189 assert!(latest_event_queue_receiver.is_empty());
1190 }
1191
1192 #[async_test]
1193 async fn test_inputs_task_stops_when_send_queue_channel_is_closed() {
1194 let registered_rooms = RwLock::new(HashMap::new());
1195 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1196 broadcast::channel(1);
1197 let (send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1198 broadcast::channel(1);
1199 let (_room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1200 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1201
1202 drop(send_queue_generic_update_sender);
1204
1205 assert!(
1207 listen_to_updates(
1208 ®istered_rooms,
1209 &mut room_event_cache_generic_update_receiver,
1210 &mut send_queue_generic_update_receiver,
1211 &mut room_info_update_receiver,
1212 &latest_event_queue_sender,
1213 )
1214 .await
1215 .is_break()
1217 );
1218
1219 assert!(latest_event_queue_receiver.is_empty());
1220 }
1221
1222 #[async_test]
1223 async fn test_inputs_task_stops_when_room_info_updates_are_closed() {
1224 let registered_rooms = RwLock::new(HashMap::new());
1225 let (_room_event_cache_generic_update_sender, mut room_event_cache_generic_update_receiver) =
1226 broadcast::channel(1);
1227 let (_send_queue_generic_update_sender, mut send_queue_generic_update_receiver) =
1228 broadcast::channel(1);
1229 let (room_info_update_sender, mut room_info_update_receiver) = broadcast::channel(1);
1230 let (latest_event_queue_sender, latest_event_queue_receiver) = mpsc::unbounded_channel();
1231
1232 drop(room_info_update_sender);
1234
1235 assert!(
1237 listen_to_updates(
1238 ®istered_rooms,
1239 &mut room_event_cache_generic_update_receiver,
1240 &mut send_queue_generic_update_receiver,
1241 &mut room_info_update_receiver,
1242 &latest_event_queue_sender,
1243 )
1244 .await
1245 .is_break()
1247 );
1248
1249 assert!(latest_event_queue_receiver.is_empty());
1250 }
1251
1252 #[async_test]
1253 async fn test_latest_event_value_is_updated_via_event_cache() {
1254 let room_id = owned_room_id!("!r0");
1255 let user_id = user_id!("@mnt_io:matrix.org");
1256 let event_factory = EventFactory::new().sender(user_id).room(&room_id);
1257 let event_id_0 = event_id!("$ev0");
1258
1259 let server = MatrixMockServer::new().await;
1260 let client = server.client_builder().build().await;
1261
1262 client.base_client().get_or_create_room(&room_id, RoomState::Joined);
1264
1265 let event_cache = client.event_cache();
1266 event_cache.subscribe().unwrap();
1267
1268 let latest_events = client.latest_events().await;
1269
1270 let mut latest_event_stream =
1272 latest_events.listen_and_subscribe_to_room(&room_id).await.unwrap().unwrap();
1273
1274 assert_pending!(latest_event_stream);
1276
1277 server
1279 .sync_room(
1280 &client,
1281 JoinedRoomBuilder::new(&room_id)
1282 .add_timeline_event(event_factory.text_msg("raclette !").event_id(event_id_0)),
1283 )
1284 .await;
1285
1286 assert_matches!(
1290 latest_event_stream.next().await,
1291 Some(LatestEventValue::Remote(RemoteLatestEventValue { kind: TimelineEventKind::PlainText { event }, .. })) => {
1292 assert_matches!(
1293 event.deserialize().unwrap(),
1294 AnySyncTimelineEvent::MessageLike(
1295 AnySyncMessageLikeEvent::RoomMessage(
1296 SyncMessageLikeEvent::Original(message_content)
1297 )
1298 ) => {
1299 assert_eq!(message_content.content.body(), "raclette !");
1300 }
1301 );
1302 }
1303 );
1304
1305 assert_pending!(latest_event_stream);
1306 }
1307
1308 #[async_test]
1309 async fn test_latest_event_value_is_initialized_by_the_event_cache_lazily() {
1310 let room_id = owned_room_id!("!r0");
1311 let user_id = user_id!("@mnt_io:matrix.org");
1312 let event_factory = EventFactory::new().sender(user_id).room(&room_id);
1313 let event_id_0 = event_id!("$ev0");
1314
1315 let server = MatrixMockServer::new().await;
1316 let client = server.client_builder().build().await;
1317
1318 {
1320 client.base_client().get_or_create_room(&room_id, RoomState::Joined);
1322
1323 client
1325 .event_cache_store()
1326 .lock()
1327 .await
1328 .expect("Could not acquire the event cache lock")
1329 .as_clean()
1330 .expect("Could not acquire a clean event cache lock")
1331 .handle_linked_chunk_updates(
1332 LinkedChunkId::Room(&room_id),
1333 vec![
1334 Update::NewItemsChunk {
1335 previous: None,
1336 new: ChunkIdentifier::new(0),
1337 next: None,
1338 },
1339 Update::PushItems {
1340 at: Position::new(ChunkIdentifier::new(0), 0),
1341 items: vec![
1342 event_factory.text_msg("hello").event_id(event_id_0).into(),
1343 ],
1344 },
1345 ],
1346 )
1347 .await
1348 .unwrap();
1349 }
1350
1351 let event_cache = client.event_cache();
1352 event_cache.subscribe().unwrap();
1353
1354 let latest_events = client.latest_events().await;
1355
1356 let mut latest_event_stream =
1357 latest_events.listen_and_subscribe_to_room(&room_id).await.unwrap().unwrap();
1358
1359 yield_now().await;
1365 assert_matches!(latest_event_stream.next_now().await, LatestEventValue::Remote(_));
1366
1367 assert_pending!(latest_event_stream);
1368 }
1369
1370 #[async_test]
1378 async fn test_latest_event_value_is_initialized_by_the_event_cache_lazily_inner() {
1379 let room_id_0 = owned_room_id!("!r0");
1380 let room_id_1 = owned_room_id!("!r1");
1381
1382 let server = MatrixMockServer::new().await;
1383 let client = server.client_builder().build().await;
1384
1385 let room_0 = client.base_client().get_or_create_room(&room_id_0, RoomState::Joined);
1387 let room_1 = client.base_client().get_or_create_room(&room_id_1, RoomState::Joined);
1388
1389 let mut room_info_1 = room_0.clone_info();
1392 room_info_1.set_latest_event(LatestEventValue::LocalIsSending(local_room_message("foo")));
1393 room_1.update_room_info(|_| (room_info_1, Default::default())).await;
1394
1395 let weak_client = WeakClient::from_client(&client);
1396
1397 let event_cache = client.event_cache();
1398 event_cache.subscribe().unwrap();
1399
1400 let (latest_event_queue_sender, mut latest_event_queue_receiver) =
1401 mpsc::unbounded_channel();
1402
1403 let registered_rooms =
1404 RegisteredRooms::new(weak_client, event_cache, &latest_event_queue_sender);
1405
1406 {
1409 let room_latest_events = registered_rooms.for_room(&room_id_0).await.unwrap().unwrap();
1410 assert_matches!(
1411 room_latest_events.read().await.for_room().get().await,
1412 LatestEventValue::None
1413 );
1414 assert_matches!(
1415 latest_event_queue_receiver.recv().await,
1416 Some(LatestEventQueueUpdate::EventCache { room_id }) => {
1417 assert_eq!(room_id, room_id_0);
1418 }
1419 );
1420 assert!(latest_event_queue_receiver.is_empty());
1421 }
1422
1423 {
1426 let room_latest_events = registered_rooms.for_room(&room_id_1).await.unwrap().unwrap();
1427 assert_matches!(
1428 room_latest_events.read().await.for_room().get().await,
1429 LatestEventValue::LocalIsSending(_)
1430 );
1431 assert!(latest_event_queue_receiver.is_empty());
1432 }
1433 }
1434
1435 #[async_test]
1436 async fn test_latest_event_value_is_updated_via_room_infos_for_invites() {
1437 let room_id = owned_room_id!("!r0");
1438 let event_factory = EventFactory::new().room(&room_id);
1439 let event_id_0 = event_id!("$ev0");
1440 let event_id_1 = event_id!("$ev1");
1441
1442 let server = MatrixMockServer::new().await;
1443 let client = server.client_builder().build().await;
1444 let own_user_id = client.user_id().unwrap();
1445 let other_user_id = user_id!("@other:servername");
1446
1447 let event_cache = client.event_cache();
1448 event_cache.subscribe().unwrap();
1449
1450 let latest_events = client.latest_events().await;
1451
1452 let mut latest_event_stream =
1454 latest_events.listen_and_subscribe_to_room(&room_id).await.unwrap().unwrap();
1455
1456 assert_pending!(latest_event_stream);
1458
1459 let now = MilliSecondsSinceUnixEpoch::now().get();
1460
1461 {
1463 server
1464 .sync_room(
1465 &client,
1466 InvitedRoomBuilder::new(&room_id).add_state_event(
1467 event_factory
1468 .member(other_user_id)
1469 .invited(own_user_id)
1470 .event_id(event_id_0),
1471 ),
1472 )
1473 .await;
1474
1475 assert_matches!(
1479 latest_event_stream.next().await,
1480 Some(LatestEventValue::RemoteInvite { event_id, timestamp, inviter }) => {
1481 assert!(event_id.is_none());
1483 assert!(timestamp.get() >= now);
1485 assert_eq!(inviter.as_deref(), Some(other_user_id));
1486 }
1487 );
1488
1489 assert_pending!(latest_event_stream);
1490 };
1491
1492 {
1494 server
1495 .sync_room(
1496 &client,
1497 InvitedRoomBuilder::new(&room_id).add_state_event(
1498 event_factory
1499 .member(other_user_id)
1500 .invited(own_user_id)
1501 .event_id(event_id_0),
1502 ),
1503 )
1504 .await;
1505
1506 assert!(timeout(Duration::from_secs(1), latest_event_stream.next()).await.is_err());
1511
1512 assert_pending!(latest_event_stream);
1513 }
1514
1515 {
1517 let now = u64::from(now) + 10; server
1519 .sync_room(
1520 &client,
1521 JoinedRoomBuilder::new(&room_id).add_timeline_event(
1522 event_factory
1523 .member(own_user_id)
1524 .membership(MembershipState::Join)
1525 .event_id(event_id_1)
1526 .server_ts(now),
1527 ),
1528 )
1529 .await;
1530
1531 assert_matches!(
1535 latest_event_stream.next().await,
1536 Some(LatestEventValue::Remote(RemoteLatestEventValue { kind: TimelineEventKind::PlainText { event }, .. })) => {
1537 assert_matches!(
1538 event.deserialize().unwrap(),
1539 AnySyncTimelineEvent::State(
1540 AnySyncStateEvent::RoomMember(
1541 SyncRoomMemberEvent::Original(event)
1542 )
1543 ) => {
1544 assert_eq!(event.event_id, event_id_1);
1545 assert_eq!(event.content.membership, MembershipState::Join);
1546 assert_eq!(event.sender, own_user_id);
1547 assert_eq!(event.state_key, own_user_id);
1548 assert_eq!(u64::from(event.origin_server_ts.get()), now);
1549 }
1550 );
1551 }
1552 );
1553
1554 assert_pending!(latest_event_stream);
1555 }
1556 }
1557}