Skip to content

Commit bd358dd

Browse files
committed
fix(auto-upload): clean stale upload entities when user delete auto upload folder
Signed-off-by: alperozturk96 <[email protected]>
1 parent d09490e commit bd358dd

5 files changed

Lines changed: 61 additions & 25 deletions

File tree

app/src/main/java/com/nextcloud/client/database/dao/SyncedFolderDao.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,14 @@ interface SyncedFolderDao {
2727

2828
@Query("SELECT * FROM ${ProviderMeta.ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME}")
2929
fun getAllAsFlow(): Flow<List<SyncedFolderEntity>>
30+
31+
@Query(
32+
"""
33+
SELECT * FROM ${ProviderMeta.ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME}
34+
WHERE ${ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH} = :remotePath
35+
AND ${ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT} = :account
36+
LIMIT 1
37+
"""
38+
)
39+
suspend fun findByRemotePathAndAccount(remotePath: String, account: String): SyncedFolderEntity?
3040
}

app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import android.content.Context
1313
import android.content.Intent
1414
import com.nextcloud.client.account.User
1515
import com.nextcloud.client.account.UserAccountManager
16+
import com.nextcloud.client.database.entity.SyncedFolderEntity
1617
import com.nextcloud.client.database.entity.UploadEntity
1718
import com.nextcloud.client.database.entity.toOCUpload
1819
import com.nextcloud.client.database.entity.toUploadEntity
@@ -40,9 +41,11 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult
4041
import com.owncloud.android.lib.common.utils.Log_OC
4142
import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation
4243
import com.owncloud.android.lib.resources.files.model.RemoteFile
44+
import com.owncloud.android.lib.resources.files.model.ServerFileInterface
4345
import com.owncloud.android.lib.resources.status.OCCapability
4446
import com.owncloud.android.operations.RemoveFileOperation
4547
import com.owncloud.android.operations.UploadFileOperation
48+
import com.owncloud.android.ui.activity.SyncedFoldersActivity
4649
import com.owncloud.android.utils.DisplayUtils
4750
import com.owncloud.android.utils.FileUtil
4851
import kotlinx.coroutines.CoroutineScope
@@ -616,4 +619,33 @@ class FileUploadHelper {
616619
}
617620
}
618621
}
622+
623+
/**
624+
* When a synced folder is disabled or deleted, its associated OCUpload entries in the uploads
625+
* table must be cleaned up. Without this, stale upload entries outlive the folder config that
626+
* created them, causing FileUploadWorker to keep retrying uploads for a folder that no longer
627+
* exists or is intentionally turned off, and AutoUploadWorker to re-queue already handled files
628+
* on its next scan via FileSystemRepository.getFilePathsWithIds.
629+
*/
630+
suspend fun removeEntityFromUploadEntities(id: Long) {
631+
uploadsStorageManager.fileSystemDao.getBySyncedFolderId(id.toString())
632+
.filter { it.localPath != null && it.remotePath != null }
633+
.forEach {
634+
Log_OC.d(
635+
TAG,
636+
"deleting upload entity localPath: ${it.localPath}, " + "remotePath: ${it.remotePath}"
637+
)
638+
uploadsStorageManager.uploadDao.deleteByLocalRemotePath(
639+
localPath = it.localPath!!,
640+
remotePath = it.remotePath!!
641+
)
642+
}
643+
}
644+
645+
suspend fun getAutoUploadFolderEntity(file: ServerFileInterface, user: User): SyncedFolderEntity? {
646+
val dao = uploadsStorageManager.syncedFolderDao
647+
val normalizedRemotePath = file.remotePath.trimEnd()
648+
if (normalizedRemotePath.isEmpty()) return null
649+
return dao.findByRemotePathAndAccount(normalizedRemotePath, user.accountName)
650+
}
619651
}

app/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.nextcloud.client.account.User;
2424
import com.nextcloud.client.database.NextcloudDatabase;
2525
import com.nextcloud.client.database.dao.FileSystemDao;
26+
import com.nextcloud.client.database.dao.SyncedFolderDao;
2627
import com.nextcloud.client.database.dao.UploadDao;
2728
import com.nextcloud.client.database.entity.UploadEntity;
2829
import com.nextcloud.client.database.entity.UploadEntityKt;
@@ -72,6 +73,7 @@ public class UploadsStorageManager extends Observable {
7273
private OCCapability capability;
7374
public final UploadDao uploadDao = NextcloudDatabase.instance().uploadDao();
7475
public final FileSystemDao fileSystemDao = NextcloudDatabase.instance().fileSystemDao();
76+
public final SyncedFolderDao syncedFolderDao = NextcloudDatabase.instance().syncedFolderDao();
7577

7678
public UploadsStorageManager(
7779
CurrentAccountProvider currentAccountProvider,

app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,21 @@ class FileDisplayActivity :
21722172
}
21732173
supportInvalidateOptionsMenu()
21742174
fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir)
2175+
2176+
// clean stale upload entities for auto upload folder
2177+
if (removedFile.isFolder) {
2178+
lifecycleScope.launch(Dispatchers.IO) {
2179+
val optionalUser = user
2180+
if (user.isEmpty) {
2181+
return@launch
2182+
}
2183+
2184+
val autoUploadFolder = fileUploadHelper
2185+
.getAutoUploadFolderEntity(removedFile, optionalUser.get()) ?: return@launch
2186+
2187+
autoUploadFolder.id?.toLong()?.let { fileUploadHelper.removeEntityFromUploadEntities(it) }
2188+
}
2189+
}
21752190
} else {
21762191
if (result.isSslRecoverableException) {
21772192
mLastSslUntrustedServerResult = result

app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -778,33 +778,10 @@ class SyncedFoldersActivity :
778778
Log_OC.d(TAG, "auto-upload configuration sync status is disabled: " + item.remotePath)
779779

780780
lifecycleScope.launch(Dispatchers.IO) {
781-
removeEntityFromUploadEntities(item.id)
781+
fileUploadHelper.removeEntityFromUploadEntities(item.id)
782782
}
783783
}
784784

785-
/**
786-
* When a synced folder is disabled or deleted, its associated OCUpload entries in the uploads
787-
* table must be cleaned up. Without this, stale upload entries outlive the folder config that
788-
* created them, causing FileUploadWorker to keep retrying uploads for a folder that no longer
789-
* exists or is intentionally turned off, and AutoUploadWorker to re-queue already handled files
790-
* on its next scan via FileSystemRepository.getFilePathsWithIds.
791-
*/
792-
private suspend fun removeEntityFromUploadEntities(id: Long) {
793-
val storageManager = fileUploadHelper.uploadsStorageManager
794-
storageManager.fileSystemDao.getBySyncedFolderId(id.toString())
795-
.filter { it.localPath != null && it.remotePath != null }
796-
.forEach {
797-
Log_OC.d(
798-
TAG,
799-
"deleting upload entity localPath: ${it.localPath}, " + "remotePath: ${it.remotePath}"
800-
)
801-
storageManager.uploadDao.deleteByLocalRemotePath(
802-
localPath = it.localPath!!,
803-
remotePath = it.remotePath!!
804-
)
805-
}
806-
}
807-
808785
override fun onDeleteSyncedFolderPreference(syncedFolder: SyncedFolderParcelable?) {
809786
if (syncedFolder == null) {
810787
return
@@ -813,7 +790,7 @@ class SyncedFoldersActivity :
813790
Log_OC.d(TAG, "deleting auto upload configuration: " + syncedFolder.remotePath)
814791

815792
lifecycleScope.launch(Dispatchers.IO) {
816-
removeEntityFromUploadEntities(syncedFolder.id)
793+
fileUploadHelper.removeEntityFromUploadEntities(syncedFolder.id)
817794
syncedFolderProvider.deleteSyncedFolder(syncedFolder.id)
818795
withContext(Dispatchers.Main) {
819796
adapter.removeItem(syncedFolder.section)

0 commit comments

Comments
 (0)