-
Notifications
You must be signed in to change notification settings - Fork 314
feat(send_queue): report progress for media uploads #5008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat(send_queue): report progress for media uploads #5008
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A really nice PR! I've a bit of feedback, but otherwise we are on the right direction.
We (the Matrix Rust team) were discussing the fact the timeline item is going to be recreated for each transmission progress update. Maybe we want a bit of throttle when broadcasting the transmission progress so that we reduce the amount of data sent to the apps. People at Element will start playing with it inside Element X, let's see how it goes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, and nice that we could in theory have this! I've got a few questions about the approach below. We'd like to try it out before validating the overall approach, because of the remark related to memory usage across the FFI, but other than that, it would be a great addition!
@jmartinesp Thanks! Can you measure if the memory peak maps to the size of the media, or is it something else? |
@jmartinesp thanks a bunch for taking the time to test the impact of this on Android! ❤️ |
Addendum to #5125 to allow sending galleries from the FFI crate. This is the final PR for galleries (apart from possible enhancements to report the upload status in #5008). This is somewhat lengthy again, apologies. Most of the changes are just wrappers and type mapping, however. So I was hoping that it's relatively straightforward to review in bulk. Happy to try and elaborate on the changes or break them up into smaller commits if that helps, however. --------- Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could avoid storing the sizes in persistent storage; after all, we're only interested in the aggregate of the remaining files to upload, so keeping this information in memory ought to be sufficient (plus, all the previously uploaded medias should still be in the event cache store until the media event is sent, at the end of the process). Let's try to make it more stateless instead.
This PR is a bit hard to review; if you introduce renamings, please keep the commit history tidy (no merge commits, only rebase/fixup! commits) and put renamings into individual commits. Also, would be sweet to group changes to the same layer (send queue vs timeline vs FFI) in commits, so as to give me a "direction" where to start from, and where to look at, in the end. You don't have to do it for this very specific PR, but for what it's worth, this is the kind of empathetic changes that usually helps (thus speeds up) reviews :)
I'd like to give this more thought and another look. Also, please add at least one end-to-end test so as to validate the approach :)
c1a2f65
to
857dcd2
Compare
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…QueueThumbnailInfo struct for easier extension Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…ting later Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…of unstable-msc4274 to use it during media progress reporting later Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…_request Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…pseudo units Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…Upload to prepare it for communicating upload progress Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
857dcd2
to
934038e
Compare
…ate::NotSentYet Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
…ntYet Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
bc57b71
to
5da557d
Compare
Codecov ReportAttention: Patch coverage is
✅ All tests successful. No failed tests found.
Additional details and impacted files@@ Coverage Diff @@
## main #5008 +/- ##
==========================================
+ Coverage 88.78% 88.80% +0.01%
==========================================
Files 334 334
Lines 91236 91414 +178
Branches 91236 91414 +178
==========================================
+ Hits 81007 81178 +171
- Misses 6400 6406 +6
- Partials 3829 3830 +1 ☔ View full report in Codecov by Sentry. |
@bnjbvr this is now ready for review again. I've addressed all previous comments other than #5008 (comment). Since I had previously made a mess out of the git history I also rebased everything into 10 self-contained commits. I will use only fix-ups from here on but wanted to try and make the base as easy to review as possible. Regarding the approach, I went for a mix of using the event cache, info from dependent requests and an in-memory cache for thumbnail sizes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks A LOT for breaking this into digestible commits; this made the review so much simpler. Overall this starts to look great, I've got a few non-trivial improvement requests that warrant another look, sorry about this. But we're reaching a nice state now. Really appreciate the test changes too 👏
Usually at this point, I'd try to help with the merging of this PR, by addressing the comments myself, but turns out I'll be away starting today and for a week or so, so I don't have much time to do this. If you're bored with this PR, I'll be happy to address my own comments when I'm back. Alternatively, another reviewer can make sure that my comments have been addressed in the meanwhile (although it'd be a bit of a stretch for them to read all the prior work).
Thanks a bunch, though; excited to get this soon!
queue_thumbnail_info: Some(( | ||
FinishUploadThumbnailInfo { txn, width: None, height: None }, | ||
thumbnail_media_request, | ||
queue_thumbnail_info: Some(QueueThumbnailInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice!
|
||
/// In-memory mapping of media transaction IDs to thumbnail sizes for the | ||
/// purpose of progress reporting. | ||
thumbnail_size_cache: Arc<Mutex<HashMap<OwnedTransactionId, Vec<Option<usize>>>>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Could we explain in the code comment the oddities about the value:
- Why do we need to store multiple thumbnail sizes for a single media transaction? As far as I understand, the transaction id is for the media event (either a regular (single) media event or a gallery event)
- Why can it be
None
? Could we store aVec<usize>
instead, and filter out the cases where there's no thumbnails? (and not even insert into this map, in this case)
- Could we use a sync mutex here, aka
matrix_sdk_common::locks::Mutex
? we might not need the async part, if the lock is only held across sync portions of the code - Out of curiosity, would it make sense to have this in
send_queue::StoreLock
, which already contains some information about the current request? (in the form ofBeingSent
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let client = room.client(); | ||
let mut req = client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: looks like client
can be inlined here, since it's only used once?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually thought that, too, but the compiler won't let me. It looks like upload_encrypted_file
borrows the client. If I inline room.client()
, the client is dropped after this statement but then later needed again in req = req.with_send_progress_observable(progress);
.
error[E0716]: temporary value dropped while borrowed
--> crates/matrix-sdk/src/send_queue/mod.rs:944:39
|
944 | let mut req = room.client()
| ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
945 | .upload_encrypted_file(&mut cursor)
946 | .with_request_config(RequestConfig::short_retry());
| - temporary value is freed at the end of this statement
...
949 | req = req.with_send_progress_observable(progress);
| --- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
|
||
/// Determine the size of a pending file upload, if this is a thumbnail | ||
/// upload or return 0 otherwise. | ||
async fn get_dependent_pending_file_upload_size( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, in the worst case, we'll have to take the event cache store lock twice, and the state store lock once, only to retrieve data that was in the stores. Since we already duplicate some of this data in the in-memory cache, we might make more use of this in-memory cache, by preemptively storing all the useful information in there, such that we don't need extra store accesses here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could also store the other needed sizes there, yes. I think we would still need the current look-ups from persisted data though because in the case of galleries, we would otherwise not have anything to report progress for the remaining gallery items?
// The progress only increases. | ||
if let Some(prev_progress) = prev_progress { | ||
assert!(progress.current >= prev_progress.current); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
…s updates Control send queue progress reporting via the send queue rather than via the client
…dQueueUpdate::MediaUpload Enable upload progress via the send queue rather than via the client builder
…tSendState::NotSentYet Enable upload progress via the send queue rather than via the client builder
…:handle_request Keep send_progress private
…dQueueUpdate::MediaUpload Correct comments of assert_update macros
…dQueueUpdate::MediaUpload Split fields of uploaded_with_progress across several lines
…dQueueUpdate::MediaUpload Clarify that index will always be zero outside of galleries
…tSendState::NotSentYet Clarify that index will always be zero outside of galleries
…::NotSentYet Clarify that index will always be zero outside of galleries
…dQueueUpdate::MediaUpload Also assert the index when asserting upload progress
…dQueueUpdate::MediaUpload Clarify what progress means for gallery uploads
…tSendState::NotSentYet Clarify what progress means for gallery uploads
…dQueueUpdate::MediaUpload Rename uploaded and pending for better clarity
…dQueueUpdate::MediaUpload Fix typo
…dQueueUpdate::MediaUpload Only check if upload progress should be reported before starting uploads
…dQueueUpdate::MediaUpload Reuse MediaUploadInfo in function parameters
…s reporting later Expand doc comment for thumbnail_size_cache
…s reporting later Switch to sync mutex
…s reporting later Move thumbnail size cache into StoreLock
…dQueueUpdate::MediaUpload Read cached thumbnail size from StoreLock
Thanks for the review. 🙏 Letting this sit until you return seems fine from my perspective. I have addressed all comments apart from those I left unresolved. PS: There was a conflict from a change on |
This makes it possible to listen to the media upload progress when using the send queue. The progress is communicated via
EventSendState::NotSentYet
.I haven't yet fixed / enhanced the tests or added a changelog because I'm not 100% sure about this approach and would like to get some preliminary feedback first.
Edit by @Hywan: