-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Parallelise uploads #16268
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
Parallelise uploads #16268
Conversation
bd4ef78 to
1a5bac6
Compare
app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt
Outdated
Show resolved
Hide resolved
@alperozturk96
alperozturk96
left a comment
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.
Hello
Thank you for the PR 👍
I really appreciate the time and effort you’ve put into this.
I wanted to share some feedback after reviewing the changes. Using ConcurrentHashMap, Semaphore, atomics, and synchronized blocks to achieve parallel uploads makes the implementation quite fragile and hard to maintain in the long run. It also increases complexity in an area of the codebase that is already fairly sensitive.
In fact, we can achieve parallel uploads with a much simpler change. Currently, in BackgroundJobManagerImpl, the startFilesUploadJob function uses the same worker tag together with the ExistingWorkPolicy.APPEND_OR_REPLACE policy. Because of this, a new worker is not used for each upload attempt; instead, uploads are queued and executed sequentially.
By making the tag unique (for example, by appending a random value), a new worker will be started for each upload, enabling parallelism with minimal changes:
val tag = startFileUploadJobTag(user.accountName + Random.nextInt())
Introducing parallel uploads is definitely a good idea, but it’s something we should approach incrementally and carefully to ensure the overall robustness of the app. FileUploadWorker is a critical component: it also triggers UI updates via the broadcast manager and is observed by multiple screens. Making it parallel will likely have side effects in those areas (notifications, upload list, file listing, etc.), so we need to be mindful of that impact.
I’d suggest the following approach:
-
Enable parallel uploads with the minimal change (unique worker tags).
-
Observe and adjust the behavior of the caller functions, and add appropriate tests.
-
Observe UI behavior (notifications, file list, upload list) and address any issues that arise.
Thanks again for your contribution and initiative on this topic. :)
@ZetaTom @tobiasKaminsky fyi.
k0raph
commented
Jan 20, 2026
Hello
Thank you for the PR 👍
I really appreciate the time and effort you’ve put into this.
I wanted to share some feedback after reviewing the changes. Using
ConcurrentHashMap,Semaphore,atomics, andsynchronizedblocks to achieve parallel uploads makes the implementation quite fragile and hard to maintain in the long run. It also increases complexity in an area of the codebase that is already fairly sensitive.In fact, we can achieve parallel uploads with a much simpler change. Currently, in
BackgroundJobManagerImpl, thestartFilesUploadJobfunction uses the same worker tag together with theExistingWorkPolicy.APPEND_OR_REPLACEpolicy. Because of this, a new worker is not used for each upload attempt; instead, uploads are queued and executed sequentially.By making the tag unique (for example, by appending a random value), a new worker will be started for each upload, enabling parallelism with minimal changes:
val tag = startFileUploadJobTag(user.accountName + Random.nextInt())Introducing parallel uploads is definitely a good idea, but it’s something we should approach incrementally and carefully to ensure the overall robustness of the app.
FileUploadWorkeris a critical component: it also triggers UI updates via the broadcast manager and is observed by multiple screens. Making it parallel will likely have side effects in those areas (notifications, upload list, file listing, etc.), so we need to be mindful of that impact.I’d suggest the following approach:
1. Enable parallel uploads with the minimal change (unique worker tags). 2. Observe and adjust the behavior of the caller functions, and add appropriate tests. 3. Observe UI behavior (notifications, file list, upload list) and address any issues that arise.Thanks again for your contribution and initiative on this topic. :)
@ZetaTom @tobiasKaminsky fyi.
Thank you @alperozturk96 for taking the time to review and I appreciate you sharing your expertise in this area. I don't disagree with any of the comments and I will happily explore your suggestion.
@alperozturk96 I have looked into your suggestion, and managed to get it working. It's significantly less changes and anecdotally seems to run much faster =]. Unfortunately it has had the side effects you mentioned. Notably the upload list is not reflective of the parallel nature (multiple files should be marked as uploading) - I am not sure how to address this without the ConcurrentHashMap solution I previously incorporated into FileUploadWorker. Could you please advise in this case?
broken-uploads-list-only-marks-1-uploading-at-a-time
Additionally the notifications are now also broken, the numerators are all over the place - I don't have a solution for this yet. Will investigate
broken-notifications
May I also clarify what you mean by "file list"?
From a design POV, "max concurrent uploads" should definitely not be a user-configurable setting. Just pick a sensible default and stick with that. If it doesn't work for everyone, we should investigate then.
k0raph
commented
Jan 22, 2026
From a design POV, "max concurrent uploads" should definitely not be a user-configurable setting. Just pick a sensible default and stick with that. If it doesn't work for everyone, we should investigate then.
Hey @kra-mo happy to remove the configurability and simply default, but could you help me understand why it "should definitely not be user configurable?". Seems like a useful reasonable option at a glance
Alternatively if the fear is that we are giving the user "a foot gun", we can provide a limited selection of options 1,2,5,10,20?
kra-mo
commented
Jan 22, 2026
It's against our design principles:
Software should get out of the way. Do things automatically instead of offering configuration options. When people ask for a setting, find out what the root of the problem is and fix that instead. Also read Choosing our Preferences.
From https://docs.nextcloud.com/server/27/developer_manual/design/introduction.html
But TL;DR the more preferences you have that most users shouldn't touch, the harder it is to find ones that they do care about. If there is no reason for something to be configurable other than "why not", it's best to just not :)
kra-mo
commented
Jan 22, 2026
If there is a need to have different numbers of for different scenarios, it'll probably come up, and we can probably solve it for that scenario automatically, as the developers. We shouldn't put the burden on the user.
k0raph
commented
Jan 22, 2026
@kra-mo great response, consider me convinced. I will revert the changes and default
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
The ICS event file has been updated to follow proper RFC 5545 formatting. Changes: - Added a valid DESCRIPTION field instead of an empty one - Unified DTSTART and DTEND to use the same TZID (Europe/Berlin) - Ensured the event duration is correct and consistent - Cleaned up extra blank lines to avoid parsing issues - Retained the complete VTIMEZONE block for compatibility with Nextcloud, Google Calendar, and iOS This improves interoperability with calendar clients and prevents parsing errors caused by mixed time formats. Signed-off-by: Gorlesunilkumar <g2005.sunil2005@gmail.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: nextcloud-android-bot <android@nextcloud.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
...ad safe vars and make sure UI updates accordingly Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
... safety Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
...progress Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: Nextcloud bot <bot@nextcloud.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: nextcloud-android-bot <android@nextcloud.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Alper Öztürk <67455295+alperozturk96@users.noreply.github.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Alper Öztürk <67455295+alperozturk96@users.noreply.github.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: Nextcloud bot <bot@nextcloud.com> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
bd5898d to
77c9265
Compare
Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
...allelise-uploads
Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.
We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.
Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6
Thank you for contributing to Nextcloud and we hope to hear from you soon!
(If you believe you should not receive this message, you can add yourself to the blocklist.)
k0raph
commented
Jan 30, 2026
@alperozturk96 @kra-mo @tobiasKaminsky could I get a re-review
Signed-off-by: Raphael Vieira <raphaelecv@hotmail.com>
tobiasKaminsky
commented
Feb 2, 2026
Hello,
thank you for this valuable PR.
Since this is a quite big (and "severe") change, I am a bit of hesitating to merge this soon.
Imagine if in some corner cases (like slow network) none of the parallel uploads finish.
Thus I think we need to have a way to test/make sure that it is robust in many cases.
We have our dev app, which we could use for that.
So I suggest to check if it is possible to bound this to "is_beta" in setup.xml?
This way we can enable it for dev versions, monitor the replies and then at some point enable it.
Before we merge it, we should also do intensive tests on our own.
Uh oh!
There was an error while loading. Please reload this page.
Issue: #10124
This PR aims to introduce improvements to the file upload process by parallelizing uploads using Kotlin Coroutines and a Semaphore (which I defaulted to 5 concurrent tasks) to improve throughput.
Key Changes
- Changing BackgroundJobManagerImpl.startFilesUploadJob() to launch multiple FileUploadWorkers
- Compatibility change in FileUploadHelper.kt
- Unit tests for FileUploadWorker.kt (extracted out dependencies to make testing easier)
- Unit tests for BackgroundJobManagerImpl.startFilesUploadJob()
- Unit test for FileUploadHelper
parallel-uploads-notification-bar parallel-uploads-uploads-list