Browse Source

Merge pull request #13218 from nextcloud/make-cancel-all-uploads-more-efficient

Make upload handling more efficient
Alper Öztürk 9 months ago
parent
commit
4d65f505f1

+ 46 - 16
app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt

@@ -33,6 +33,7 @@ import com.owncloud.android.lib.resources.files.model.RemoteFile
 import com.owncloud.android.operations.UploadFileOperation
 import com.owncloud.android.utils.FileUtil
 import java.io.File
+import java.util.concurrent.Semaphore
 import javax.inject.Inject
 
 @Suppress("TooManyFunctions")
@@ -58,6 +59,8 @@ class FileUploadHelper {
 
         private var instance: FileUploadHelper? = null
 
+        private val retryFailedUploadsSemaphore = Semaphore(1)
+
         fun instance(): FileUploadHelper {
             return instance ?: synchronized(this) {
                 instance ?: FileUploadHelper().also { instance = it }
@@ -75,19 +78,27 @@ class FileUploadHelper {
         accountManager: UserAccountManager,
         powerManagementService: PowerManagementService
     ) {
-        val failedUploads = uploadsStorageManager.failedUploads
-        if (failedUploads == null || failedUploads.isEmpty()) {
-            Log_OC.d(TAG, "Failed uploads are empty or null")
-            return
-        }
+        if (retryFailedUploadsSemaphore.tryAcquire()) {
+            try {
+                val failedUploads = uploadsStorageManager.failedUploads
+                if (failedUploads == null || failedUploads.isEmpty()) {
+                    Log_OC.d(TAG, "Failed uploads are empty or null")
+                    return
+                }
 
-        retryUploads(
-            uploadsStorageManager,
-            connectivityService,
-            accountManager,
-            powerManagementService,
-            failedUploads
-        )
+                retryUploads(
+                    uploadsStorageManager,
+                    connectivityService,
+                    accountManager,
+                    powerManagementService,
+                    failedUploads
+                )
+            } finally {
+                retryFailedUploadsSemaphore.release()
+            }
+        } else {
+            Log_OC.d(TAG, "Skip retryFailedUploads since it is already running")
+        }
     }
 
     fun retryCancelledUploads(
@@ -139,6 +150,10 @@ class FileUploadHelper {
 
             if (uploadResult != UploadResult.UPLOADED) {
                 if (failedUpload.lastResult != uploadResult) {
+                    // Setting Upload status else cancelled uploads will behave wrong, when retrying
+                    // Needs to happen first since lastResult wil be overwritten by setter
+                    failedUpload.uploadStatus = UploadStatus.UPLOAD_FAILED
+
                     failedUpload.lastResult = uploadResult
                     uploadsStorageManager.updateUpload(failedUpload)
                 }
@@ -204,10 +219,25 @@ class FileUploadHelper {
     }
 
     fun cancelFileUpload(remotePath: String, accountName: String) {
-        uploadsStorageManager.getUploadByRemotePath(remotePath).run {
-            removeFileUpload(remotePath, accountName)
-            uploadStatus = UploadStatus.UPLOAD_CANCELLED
-            uploadsStorageManager.storeUpload(this)
+        val upload = uploadsStorageManager.getUploadByRemotePath(remotePath)
+        if (upload != null) {
+            cancelFileUploads(listOf(upload), accountName)
+        } else {
+            Log_OC.e(TAG, "Error cancelling current upload because upload does not exist!")
+        }
+    }
+
+    fun cancelFileUploads(uploads: List<OCUpload>, accountName: String) {
+        for (upload in uploads) {
+            upload.uploadStatus = UploadStatus.UPLOAD_CANCELLED
+            uploadsStorageManager.updateUpload(upload)
+        }
+
+        try {
+            val user = accountManager.getUser(accountName).get()
+            cancelAndRestartUploadJob(user)
+        } catch (e: NoSuchElementException) {
+            Log_OC.e(TAG, "Error restarting upload job because user does not exist!")
         }
     }
 

+ 9 - 6
app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java

@@ -56,6 +56,7 @@ import com.owncloud.android.utils.theme.ViewThemeUtils;
 
 import java.io.File;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Optional;
 
 import androidx.annotation.NonNull;
@@ -119,10 +120,12 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         headerViewHolder.binding.uploadListAction.setOnClickListener(v -> {
             switch (group.type) {
                 case CURRENT -> {
-                    for (OCUpload upload : group.getItems()) {
-                        uploadHelper.cancelFileUpload(upload.getRemotePath(), upload.getAccountName());
-                    }
-                    loadUploadItemsFromDb();
+                    new Thread(() -> {
+                        uploadHelper.cancelFileUploads(
+                            Arrays.asList(group.items),
+                            group.getItem(0).getAccountName());
+                        parentActivity.runOnUiThread(this::loadUploadItemsFromDb);
+                    }).start();
                 }
                 case FINISHED -> {
                     uploadsStorageManager.clearSuccessfulUploads();
@@ -152,7 +155,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
 
                 // FIXME For e2e resume is not working
                 new Thread(() -> {
-                    FileUploadHelper.Companion.instance().retryFailedUploads(
+                    uploadHelper.retryFailedUploads(
                         uploadsStorageManager,
                         connectivityService,
                         accountManager,
@@ -196,7 +199,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
     // FIXME For e2e resume is not working
     private void retryCancelledUploads() {
         new Thread(() -> {
-            boolean showNotExistMessage = FileUploadHelper.Companion.instance().retryCancelledUploads(
+            boolean showNotExistMessage = uploadHelper.retryCancelledUploads(
                 uploadsStorageManager,
                 connectivityService,
                 accountManager,