Browse Source

Merge pull request #10926 from nextcloud/fix/multiple-upload-workers

FilesUploadWorker: ensure only one worker can be running for the same user
Álvaro Brey 2 years ago
parent
commit
25a054938d

+ 7 - 1
app/src/androidTest/java/com/owncloud/android/files/services/FileUploadWorkerIT.kt

@@ -22,11 +22,17 @@
 
 package com.owncloud.android.files.services
 
+import org.junit.After
 import org.junit.Before
 
 class FileUploadWorkerIT : FileUploaderIT() {
     @Before
-    fun enableWorker() {
+    fun forceUploadWorker() {
         FileUploader.setForceNewUploadWorker(true)
     }
+
+    @After
+    fun resetForceUploadWorker() {
+        FileUploader.setForceNewUploadWorker(false)
+    }
 }

+ 1 - 1
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt

@@ -455,7 +455,7 @@ internal class BackgroundJobManagerImpl(
             .setInputData(data)
             .build()
 
-        workManager.enqueue(request)
+        workManager.enqueueUniqueWork(JOB_FILES_UPLOAD + user.accountName, ExistingWorkPolicy.KEEP, request)
     }
 
     override fun getFileUploads(user: User): LiveData<List<JobInfo>> {

+ 18 - 6
app/src/main/java/com/nextcloud/client/jobs/FilesUploadWorker.kt

@@ -27,7 +27,6 @@ import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
 import android.os.Build
-import android.text.TextUtils
 import androidx.core.app.NotificationCompat
 import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import androidx.work.Worker
@@ -74,14 +73,29 @@ class FilesUploadWorker(
 
     override fun doWork(): Result {
         val accountName = inputData.getString(ACCOUNT)
-        if (TextUtils.isEmpty(accountName)) {
+        if (accountName.isNullOrEmpty()) {
+            Log_OC.w(TAG, "User was null for file upload worker")
             return Result.failure() // user account is needed
         }
 
+        // get all pending uploads
+        var currentAndPendingUploadsForAccount =
+            uploadsStorageManager.getCurrentAndPendingUploadsForAccount(accountName)
+        while (currentAndPendingUploadsForAccount.isNotEmpty()) {
+            Log_OC.d(TAG, "Handling ${currentAndPendingUploadsForAccount.size} uploads for account $accountName")
+            handlePendingUploads(currentAndPendingUploadsForAccount, accountName)
+            currentAndPendingUploadsForAccount =
+                uploadsStorageManager.getCurrentAndPendingUploadsForAccount(accountName)
+        }
+
+        Log_OC.d(TAG, "No more pending uploads for account $accountName, stopping work")
+        return Result.success()
+    }
+
+    private fun handlePendingUploads(uploads: Array<OCUpload>, accountName: String) {
         val user = userAccountManager.getUser(accountName)
 
-        // get all pending uploads
-        for (upload in uploadsStorageManager.getCurrentAndPendingUploadsForAccount(accountName!!)) {
+        for (upload in uploads) {
             // create upload file operation
             if (user.isPresent) {
                 val uploadFileOperation = createUploadFileOperation(upload, user.get())
@@ -100,8 +114,6 @@ class FilesUploadWorker(
                 uploadsStorageManager.removeUpload(upload.uploadId)
             }
         }
-
-        return Result.success()
     }
 
     /**