From c191eb7cd110d540e92fb6ff57f1d094d44a4375 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 7 Jul 2025 19:58:29 +0200 Subject: [PATCH] feat(send_queue): cache thumbnail sizes to use them in progress reporting later Signed-off-by: Johannes Marbach --- crates/matrix-sdk/src/send_queue/mod.rs | 54 +++++++++++++++++++--- crates/matrix-sdk/src/send_queue/upload.rs | 2 + 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/crates/matrix-sdk/src/send_queue/mod.rs b/crates/matrix-sdk/src/send_queue/mod.rs index 77177d10f..d6fb8c4bf 100644 --- a/crates/matrix-sdk/src/send_queue/mod.rs +++ b/crates/matrix-sdk/src/send_queue/mod.rs @@ -318,6 +318,9 @@ struct QueueThumbnailInfo { /// The thumbnail's mime type. content_type: Mime, + + /// The thumbnail's file size in bytes. + file_size: usize, } /// A specific room's send queue ran into an error, and it has disabled itself. @@ -998,6 +1001,20 @@ struct StoreLock { /// /// Also used as the lock to access the state store. being_sent: Arc>>, + + /// In-memory mapping of media transaction IDs to thumbnail sizes for the + /// purpose of progress reporting. + /// + /// The keys are the transaction IDs for sending the media or gallery event + /// after all uploads have finished. This allows us to easily clean up the + /// cache after the event was sent. + /// + /// For media uploads, the value vector will always have a single element. + /// + /// For galleries, some gallery items might not have a thumbnail while + /// others do. Since we access the thumbnails by their index within the + /// gallery, the vector needs to hold optional usize's. + thumbnail_size_cache: Arc>>>>, } impl StoreLock { @@ -1006,6 +1023,7 @@ impl StoreLock { StoreLockGuard { client: self.client.clone(), being_sent: self.being_sent.clone().lock_owned().await, + thumbnail_size_cache: self.thumbnail_size_cache.clone().lock_owned().await, } } } @@ -1019,6 +1037,10 @@ struct StoreLockGuard { /// The one queued request that is being sent at the moment, along with /// associated data that can be useful to act upon it. being_sent: OwnedMutexGuard>, + + /// In-memory mapping of media transaction IDs to thumbnail sizes for the + /// purpose of progress reporting. + thumbnail_size_cache: OwnedMutexGuard>>>, } impl StoreLockGuard { @@ -1047,7 +1069,14 @@ impl QueueStorage { /// Create a new queue for queuing requests to be sent later. fn new(client: WeakClient, room: OwnedRoomId) -> Self { - Self { room_id: room, store: StoreLock { client, being_sent: Default::default() } } + Self { + room_id: room, + store: StoreLock { + client, + being_sent: Default::default(), + thumbnail_size_cache: Default::default(), + }, + } } /// Push a new event to be sent in the queue, with a default priority of 0. @@ -1204,6 +1233,8 @@ impl QueueStorage { warn!(txn_id = %transaction_id, "request marked as sent was missing from storage"); } + guard.thumbnail_size_cache.remove(transaction_id); + Ok(()) } @@ -1217,7 +1248,7 @@ impl QueueStorage { &self, transaction_id: &TransactionId, ) -> Result { - let guard = self.store.lock().await; + let mut guard = self.store.lock().await; if guard.being_sent.as_ref().map(|info| info.transaction_id.as_ref()) == Some(transaction_id) @@ -1244,6 +1275,8 @@ impl QueueStorage { .remove_send_queue_request(&self.room_id, transaction_id) .await?; + guard.thumbnail_size_cache.remove(transaction_id); + Ok(removed) } @@ -1302,10 +1335,12 @@ impl QueueStorage { file_media_request: MediaRequestParameters, thumbnail: Option, ) -> Result<(), RoomSendQueueStorageError> { - let guard = self.store.lock().await; + let mut guard = self.store.lock().await; let client = guard.client()?; let store = client.state_store(); + let media_sizes = vec![thumbnail.as_ref().map(|t| t.file_size)]; + let thumbnail_info = self .push_thumbnail_and_media_uploads( store, @@ -1323,7 +1358,7 @@ impl QueueStorage { .save_dependent_queued_request( &self.room_id, &upload_file_txn, - send_event_txn.into(), + send_event_txn.clone().into(), created_at, DependentQueuedRequestKind::FinishUpload { local_echo: Box::new(event), @@ -1333,6 +1368,8 @@ impl QueueStorage { ) .await?; + guard.thumbnail_size_cache.insert(send_event_txn, media_sizes); + Ok(()) } @@ -1348,11 +1385,12 @@ impl QueueStorage { created_at: MilliSecondsSinceUnixEpoch, item_queue_infos: Vec, ) -> Result<(), RoomSendQueueStorageError> { - let guard = self.store.lock().await; + let mut guard = self.store.lock().await; let client = guard.client()?; let store = client.state_store(); let mut finish_item_infos = Vec::with_capacity(item_queue_infos.len()); + let mut media_sizes = Vec::with_capacity(item_queue_infos.len()); let Some((first, rest)) = item_queue_infos.split_first() else { return Ok(()); @@ -1375,6 +1413,7 @@ impl QueueStorage { finish_item_infos .push(FinishGalleryItemInfo { file_upload: upload_file_txn.clone(), thumbnail_info }); + media_sizes.push(thumbnail.as_ref().map(|t| t.file_size)); let mut last_upload_file_txn = upload_file_txn.clone(); @@ -1439,6 +1478,7 @@ impl QueueStorage { file_upload: upload_file_txn.clone(), thumbnail_info: thumbnail_info.cloned(), }); + media_sizes.push(thumbnail.as_ref().map(|t| t.file_size)); last_upload_file_txn = upload_file_txn.clone(); } @@ -1449,7 +1489,7 @@ impl QueueStorage { .save_dependent_queued_request( &self.room_id, &last_upload_file_txn, - send_event_txn.into(), + send_event_txn.clone().into(), created_at, DependentQueuedRequestKind::FinishGallery { local_echo: Box::new(event), @@ -1458,6 +1498,8 @@ impl QueueStorage { ) .await?; + guard.thumbnail_size_cache.insert(send_event_txn, media_sizes); + Ok(()) } diff --git a/crates/matrix-sdk/src/send_queue/upload.rs b/crates/matrix-sdk/src/send_queue/upload.rs index ba7a2fde7..c12b5d496 100644 --- a/crates/matrix-sdk/src/send_queue/upload.rs +++ b/crates/matrix-sdk/src/send_queue/upload.rs @@ -445,6 +445,7 @@ impl RoomSendQueue { // Create the information required for filling the thumbnail section of the // event. let (data, content_type, thumbnail_info) = thumbnail.into_parts(); + let file_size = data.len(); // Cache thumbnail in the cache store. let thumbnail_media_request = Media::make_local_file_media_request(&txn); @@ -472,6 +473,7 @@ impl RoomSendQueue { }, media_request_parameters: thumbnail_media_request, content_type, + file_size, }), }) } else {