From f186d2621ae81ab8e597cfbb9136e8be827c7702 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 20 Mar 2026 10:00:26 +0100 Subject: [PATCH 1/3] fix(auto-upload): do not process upload entity belongs to auto upload in file upload worker Signed-off-by: alperozturk96 --- .../client/database/dao/FileSystemDao.kt | 10 ++++++++ .../client/jobs/BackgroundJobFactory.kt | 2 ++ .../jobs/autoUpload/FileSystemRepository.kt | 2 ++ .../client/jobs/upload/FileUploadWorker.kt | 25 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt b/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt index 9d9be7179d3c..16e5db119231 100644 --- a/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt +++ b/app/src/main/java/com/nextcloud/client/database/dao/FileSystemDao.kt @@ -17,6 +17,16 @@ import com.owncloud.android.db.ProviderMeta @Dao interface FileSystemDao { + @Query( + """ + SELECT COUNT(*) > 0 FROM ${ProviderMeta.ProviderTableMeta.FILESYSTEM_TABLE_NAME} + WHERE ${ProviderMeta.ProviderTableMeta.FILESYSTEM_FILE_LOCAL_PATH} = :localPath + AND ${ProviderMeta.ProviderTableMeta.FILESYSTEM_SYNCED_FOLDER_ID} IS NOT NULL + LIMIT 1 +""" + ) + suspend fun isBelongToAnyAutoFolder(localPath: String): Boolean + @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertOrReplace(filesystemEntity: FilesystemEntity) diff --git a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt index a5a1a7f8ab35..5e573b1c4cd0 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt @@ -244,6 +244,8 @@ class BackgroundJobFactory @Inject constructor( localBroadcastManager.get(), backgroundJobManager.get(), preferences, + FileSystemRepository(dao = database.fileSystemDao(), uploadsStorageManager, context), + syncedFolderProvider, context, params ) diff --git a/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt b/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt index 59203b7cc619..671e9b1974d5 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/autoUpload/FileSystemRepository.kt @@ -35,6 +35,8 @@ class FileSystemRepository( const val BATCH_SIZE = 50 } + suspend fun isBelongToAnyAutoFolder(localPath: String): Boolean = dao.isBelongToAnyAutoFolder(localPath) + fun deleteAutoUploadAndUploadEntity(syncedFolder: SyncedFolder, localPath: String, entity: FilesystemEntity) { Log_OC.d(TAG, "deleting auto upload entity and upload entity") diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index d2b9b4d7d077..dceda4c30d56 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -19,6 +19,8 @@ import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.device.PowerManagementService import com.nextcloud.client.jobs.BackgroundJobManager import com.nextcloud.client.jobs.BackgroundJobManagerImpl +import com.nextcloud.client.jobs.autoUpload.FileSystemRepository +import com.nextcloud.client.jobs.autoUpload.SyncFolderHelper import com.nextcloud.client.jobs.utils.UploadErrorNotificationManager import com.nextcloud.client.network.ConnectivityService import com.nextcloud.client.preferences.AppPreferences @@ -28,6 +30,7 @@ import com.nextcloud.utils.extensions.updateStatus import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.ForegroundServiceType +import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.ThumbnailsCacheManager import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.db.OCUpload @@ -57,6 +60,8 @@ class FileUploadWorker( val localBroadcastManager: LocalBroadcastManager, private val backgroundJobManager: BackgroundJobManager, val preferences: AppPreferences, + val filesystemRepository: FileSystemRepository, + val syncedFolderProvider: SyncedFolderProvider, val context: Context, params: WorkerParameters ) : CoroutineWorker(context, params), @@ -219,10 +224,20 @@ class FileUploadWorker( val uploads = uploadsStorageManager.getUploadsByIds(uploadIds, accountName) val ocAccount = OwnCloudAccount(user.toPlatformAccount(), context) val client = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context) + val syncFolderHelper = SyncFolderHelper(context) for ((index, upload) in uploads.withIndex()) { ensureActive() + if (isBelongToAnySyncedFolder(upload, syncFolderHelper)) { + Log_OC.d(TAG, "skipping upload, will be handled by AutoUploadWorker: ${upload.localPath}") + uploadsStorageManager.uploadDao.deleteByRemotePathAndAccountName( + remotePath = upload.remotePath, + accountName = accountName + ) + continue + } + if (preferences.isGlobalUploadPaused) { Log_OC.d(TAG, "Upload is paused, skip uploading files!") notificationManager.notifyPaused( @@ -266,6 +281,16 @@ class FileUploadWorker( return@withContext Result.success() } + suspend fun isBelongToAnySyncedFolder(upload: OCUpload, syncFolderHelper: SyncFolderHelper): Boolean { + if (!filesystemRepository.isBelongToAnyAutoFolder(upload.localPath)) return false + + return syncedFolderProvider.syncedFolders.any { folder -> + val file = File(upload.localPath) + val expectedRemotePath = syncFolderHelper.getAutoUploadRemotePath(folder, file) + expectedRemotePath == upload.remotePath + } + } + private fun sendUploadFinishEvent( totalUploadSize: Int, currentUploadIndex: Int, From bb052f86880f837514f441fb55232480be4257a4 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 20 Mar 2026 10:32:59 +0100 Subject: [PATCH 2/3] performance improvements Signed-off-by: alperozturk96 --- .../nextcloud/client/jobs/upload/FileUploadWorker.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index dceda4c30d56..7adfc5bc03de 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -30,6 +30,7 @@ import com.nextcloud.utils.extensions.updateStatus import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.ForegroundServiceType +import com.owncloud.android.datamodel.SyncedFolder import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.ThumbnailsCacheManager import com.owncloud.android.datamodel.UploadsStorageManager @@ -225,11 +226,12 @@ class FileUploadWorker( val ocAccount = OwnCloudAccount(user.toPlatformAccount(), context) val client = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context) val syncFolderHelper = SyncFolderHelper(context) + val syncedFolders = syncedFolderProvider.syncedFolders for ((index, upload) in uploads.withIndex()) { ensureActive() - if (isBelongToAnySyncedFolder(upload, syncFolderHelper)) { + if (isBelongToAnySyncedFolder(upload, syncFolderHelper, syncedFolders)) { Log_OC.d(TAG, "skipping upload, will be handled by AutoUploadWorker: ${upload.localPath}") uploadsStorageManager.uploadDao.deleteByRemotePathAndAccountName( remotePath = upload.remotePath, @@ -281,10 +283,14 @@ class FileUploadWorker( return@withContext Result.success() } - suspend fun isBelongToAnySyncedFolder(upload: OCUpload, syncFolderHelper: SyncFolderHelper): Boolean { + suspend fun isBelongToAnySyncedFolder( + upload: OCUpload, + syncFolderHelper: SyncFolderHelper, + syncedFolders: List + ): Boolean { if (!filesystemRepository.isBelongToAnyAutoFolder(upload.localPath)) return false - return syncedFolderProvider.syncedFolders.any { folder -> + return syncedFolders.any { folder -> val file = File(upload.localPath) val expectedRemotePath = syncFolderHelper.getAutoUploadRemotePath(folder, file) expectedRemotePath == upload.remotePath From 7f834c9ba8194ef8fa54cd326bb85ff036c1a530 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 20 Mar 2026 10:34:01 +0100 Subject: [PATCH 3/3] check file before getting remote path Signed-off-by: alperozturk96 --- .../java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index 7adfc5bc03de..9bf2c366a2dc 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -26,6 +26,7 @@ import com.nextcloud.client.network.ConnectivityService import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.utils.ForegroundServiceHelper import com.nextcloud.utils.extensions.getPercent +import com.nextcloud.utils.extensions.toFile import com.nextcloud.utils.extensions.updateStatus import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager @@ -291,7 +292,7 @@ class FileUploadWorker( if (!filesystemRepository.isBelongToAnyAutoFolder(upload.localPath)) return false return syncedFolders.any { folder -> - val file = File(upload.localPath) + val file = upload.localPath.toFile() ?: return false val expectedRemotePath = syncFolderHelper.getAutoUploadRemotePath(folder, file) expectedRemotePath == upload.remotePath }