Commit cabc67b5cc05
tarball3 files changed+127-21
@@ -255,6 +255,7 @@ impl SendQueue {
255255
&self.client,256256
owned_room_id.clone(),257257
data.report_media_upload_progress.clone(),258
+ data.report_global_upload_progress.clone(),258259
);259260
260261
map.insert(owned_room_id, room_q.clone());@@ -297,6 +298,17 @@ impl SendQueue {
297298
self.data().report_media_upload_progress.store(enabled, Ordering::SeqCst);298299
}299300
301
+ /// Enable or disable sending media upload progress updates302
+ /// ([`RoomSendQueueUpdate::MediaUpload`]) to the global listeners of303
+ /// [`SendQueue::subscribe`], in addition to the room's listeners.304
+ ///305
+ /// Incremental progress is only reported if it's been enabled with306
+ /// [`SendQueue::enable_upload_progress`]; otherwise, only the final307
+ /// update of each upload is sent.308
+ pub fn enable_global_upload_progress(&self, enabled: bool) {309
+ self.data().report_global_upload_progress.store(enabled, Ordering::SeqCst);310
+ }311
+300312
/// Subscribe to all updates for all rooms.301313
///302314
/// Use [`RoomSendQueue::subscribe`] to subscribe to update for a _specific@@ -402,6 +414,10 @@ pub(super) struct SendQueueData {
402414
403415
/// Will media upload progress be reported via send queue updates?404416
report_media_upload_progress: Arc<AtomicBool>,417
+418
+ /// Will media upload progress updates be sent to the global listeners419
+ /// too?420
+ report_global_upload_progress: Arc<AtomicBool>,405421
}406422
407423
impl SendQueueData {@@ -417,6 +433,7 @@ impl SendQueueData {
417433
error_sender,418434
is_dropping: Arc::new(false.into()),419435
report_media_upload_progress: Arc::new(false.into()),436
+ report_global_upload_progress: Arc::new(false.into()),420437
}421438
}422439
}@@ -466,6 +483,7 @@ impl RoomSendQueue {
466483
client: &Client,467484
room_id: OwnedRoomId,468485
report_media_upload_progress: Arc<AtomicBool>,486
+ report_global_upload_progress: Arc<AtomicBool>,469487
) -> Self {470488
let (update_sender, _) = broadcast::channel(32);471489
@@ -487,6 +505,7 @@ impl RoomSendQueue {
487505
global_error_sender,488506
is_dropping,489507
report_media_upload_progress,508
+ report_global_upload_progress,490509
),491510
);492511
@@ -665,6 +684,7 @@ impl RoomSendQueue {
665684
global_error_sender: broadcast::Sender<SendQueueRoomError>,666685
is_dropping: Arc<AtomicBool>,667686
report_media_upload_progress: Arc<AtomicBool>,687
+ report_global_upload_progress: Arc<AtomicBool>,668688
) {669689
trace!("spawned the sending task");670690
@@ -756,7 +776,10 @@ impl RoomSendQueue {
756776
let progress = RoomSendQueue::create_media_upload_progress_observable(757777
&media_upload_progress_info,758778
related_to,779
+ room_id,780
+ &global_update_sender,759781
&update_sender,782
+ &report_global_upload_progress,760783
);761784
762785
(Some(media_upload_progress_info), Some(progress))@@ -883,14 +906,20 @@ impl RoomSendQueue {
883906
})884907
.unwrap_or(AbstractProgress { current: 1, total: 1 });885908
886
- // Purposefully don't use `send_update` here, because we don't want to887
- // notify the global listeners about an upload progress update.888
- let _ = update_sender.send(RoomSendQueueUpdate::MediaUpload {889
- related_to: related_txn_id.as_ref().unwrap_or(&txn_id).clone(),890
- file: Some(sent_media_info.file),891
- index,892
- progress,893
- });909
+ // Purposefully don't use `send_update` here, because the global910
+ // listeners only get upload progress updates when they asked for them.911
+ send_upload_progress(912
+ &global_update_sender,913
+ &update_sender,914
+ room_id,915
+ &report_global_upload_progress,916
+ RoomSendQueueUpdate::MediaUpload {917
+ related_to: related_txn_id.as_ref().unwrap_or(&txn_id).clone(),918
+ file: Some(sent_media_info.file),919
+ index,920
+ progress,921
+ },922
+ );894923
}895924
896925
SentRequestKey::Redaction { event_id, redacts, reason } => {@@ -1252,6 +1281,23 @@ fn send_update(
12521281
let _ = global_update_sender.send(SendQueueUpdate { room_id: room_id.to_owned(), update });12531282
}12541283
1284
+/// Send a media upload progress update to the room's listeners, and to the1285
+/// global listeners only if [`SendQueue::enable_global_upload_progress`] was1286
+/// called.1287
+fn send_upload_progress(1288
+ global_update_sender: &broadcast::Sender<SendQueueUpdate>,1289
+ update_sender: &broadcast::Sender<RoomSendQueueUpdate>,1290
+ room_id: &RoomId,1291
+ report_global_upload_progress: &AtomicBool,1292
+ update: RoomSendQueueUpdate,1293
+) {1294
+ if report_global_upload_progress.load(Ordering::SeqCst) {1295
+ send_update(global_update_sender, update_sender, room_id, update);1296
+ } else {1297
+ let _ = update_sender.send(update);1298
+ }1299
+}1300
+12551301
impl From<&crate::Error> for QueueWedgeError {12561302
fn from(value: &crate::Error) -> Self {12571303
match value {@@ -3388,7 +3434,9 @@ mod tests {
33883434
let react_id = ChildTransactionId::new();33893435
let react = DependentQueuedRequest {33903436
own_transaction_id: react_id.clone(),3391
- kind: DependentQueuedRequestKind::ReactEvent { key: "🧠".to_owned(), shortcode: None },3437
+ kind: DependentQueuedRequestKind::ReactEvent {3438
+ key: "🧠".to_owned(), shortcode: None3439
+ },33923440
parent_transaction_id: txn.clone(),33933441
parent_key: None,33943442
created_at: MilliSecondsSinceUnixEpoch::now(),@@ -14,20 +14,26 @@
1414
1515
//! Progress facilities for the media upload system.1616
17
-use std::ops::Add;17
+use std::{18
+ ops::Add,19
+ sync::{Arc, atomic::AtomicBool},20
+};1821
1922
use eyeball::SharedObservable;2023
#[cfg(feature = "unstable-msc4274")]2124
use matrix_sdk_base::store::AccumulatedSentMediaInfo;2225
use matrix_sdk_base::{media::MediaRequestParameters, store::DependentQueuedRequestKind};2326
use matrix_sdk_common::executor::spawn;24
-use ruma::{TransactionId, events::room::MediaSource};27
+use ruma::{RoomId, TransactionId, events::room::MediaSource};2528
use tokio::sync::broadcast;2629
use tracing::warn;2730
2831
use crate::{2932
Room, TransmissionProgress,30
- send_queue::{QueueStorage, RoomSendQueue, RoomSendQueueStorageError, RoomSendQueueUpdate},33
+ send_queue::{34
+ QueueStorage, RoomSendQueue, RoomSendQueueStorageError, RoomSendQueueUpdate,35
+ SendQueueUpdate, send_upload_progress,36
+ },3137
};3238
3339
/// Progress of an operation in abstract units.@@ -208,13 +214,19 @@ impl RoomSendQueue {
208214
pub(super) fn create_media_upload_progress_observable(209215
media_upload_info: &MediaUploadProgressInfo,210216
related_txn_id: &TransactionId,217
+ room_id: &RoomId,218
+ global_update_sender: &broadcast::Sender<SendQueueUpdate>,211219
update_sender: &broadcast::Sender<RoomSendQueueUpdate>,220
+ report_global_upload_progress: &Arc<AtomicBool>,212221
) -> SharedObservable<TransmissionProgress> {213222
let progress: SharedObservable<TransmissionProgress> = Default::default();214223
let mut subscriber = progress.subscribe();215224
216225
let related_txn_id = related_txn_id.to_owned();226
+ let room_id = room_id.to_owned();227
+ let global_update_sender = global_update_sender.clone();217228
let update_sender = update_sender.clone();229
+ let report_global_upload_progress = report_global_upload_progress.clone();218230
let media_upload_info = *media_upload_info;219231
220232
// Watch and communicate the progress on a detached background task. Once@@ -222,15 +234,21 @@ impl RoomSendQueue {
222234
// task will end.223235
spawn(async move {224236
while let Some(progress) = subscriber.next().await {225
- // Purposefully don't use `send_update` here, because we don't want to notify226
- // the global listeners about an upload progress update.227
- let _ = update_sender.send(RoomSendQueueUpdate::MediaUpload {228
- related_to: related_txn_id.clone(),229
- file: None,230
- index: media_upload_info.index,231
- progress: estimate_media_upload_progress(progress, media_upload_info.bytes)232
- + media_upload_info.offsets,233
- });237
+ // Purposefully don't use `send_update` here, because the global listeners238
+ // only get upload progress updates when they asked for them.239
+ send_upload_progress(240
+ &global_update_sender,241
+ &update_sender,242
+ &room_id,243
+ &report_global_upload_progress,244
+ RoomSendQueueUpdate::MediaUpload {245
+ related_to: related_txn_id.clone(),246
+ file: None,247
+ index: media_upload_info.index,248
+ progress: estimate_media_upload_progress(progress, media_upload_info.bytes)249
+ + media_upload_info.offsets,250
+ },251
+ );234252
}235253
});236254
@@ -2991,6 +2991,46 @@ async fn abort_and_verify(
29912991
}29922992
29932993
#[async_test]2994
+async fn test_global_upload_progress() {2995
+ let mock = MatrixMockServer::new().await;2996
+2997
+ let room_id = room_id!("!a:b.c");2998
+ let client = mock.client_builder().build().await;2999
+ let room = mock.sync_joined_room(&client, room_id).await;3000
+3001
+ // Enabling global upload progress applies to an existing room queue.3002
+ let q = room.send_queue();3003
+ client.send_queue().enable_upload_progress(true);3004
+ client.send_queue().enable_global_upload_progress(true);3005
+ let mut global_watch = client.send_queue().subscribe();3006
+3007
+ mock.mock_authenticated_media_config().ok_default().mount().await;3008
+ mock.mock_room_state_encryption().plain().mount().await;3009
+ mock.mock_upload().ok(mxc_uri!("mxc://sdk.rs/media")).mock_once().mount().await;3010
+ mock.mock_room_send().ok(event_id!("$media")).mock_once().mount().await;3011
+3012
+ queue_attachment_no_thumbnail(&q).await;3013
+3014
+ let mut uploaded_file = None;3015
+ loop {3016
+ let update = timeout(Duration::from_secs(5), global_watch.recv()).await.unwrap().unwrap();3017
+ assert_eq!(update.room_id, room_id);3018
+ match update.update {3019
+ RoomSendQueueUpdate::MediaUpload { file, .. } => {3020
+ if file.is_some() {3021
+ uploaded_file = file;3022
+ }3023
+ }3024
+ RoomSendQueueUpdate::SentEvent { .. } => break,3025
+ _ => {}3026
+ }3027
+ }3028
+3029
+ assert_let!(Some(MediaSource::Plain(mxc)) = uploaded_file);3030
+ assert_eq!(mxc, mxc_uri!("mxc://sdk.rs/media"));3031
+}3032
+3033
+#[async_test]29943034
async fn test_media_event_is_sent_in_order() {29953035
// Test that despite happening in multiple requests, sending a media maintains29963036
// the ordering.