Skip to content

Commit 184278c

Browse files
Merge pull request #16144 from nextcloud/handle/metadata-worker-edge-cases
handle metadata worker edge cases
2 parents 3f5b20b + dd0e339 commit 184278c

File tree

3 files changed

+68
-17
lines changed

3 files changed

+68
-17
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ interface FileDao {
7979
AND file_owner = :accountName
8080
AND is_encrypted = 0
8181
AND (content_type = :dirType OR content_type = :webdavType)
82-
ORDER BY ${ProviderTableMeta.FILE_DEFAULT_SORT_ORDER}
82+
ORDER BY ${ProviderTableMeta._ID} ASC
8383
"""
8484
)
8585
fun getNonEncryptedSubfolders(

app/src/main/java/com/nextcloud/client/jobs/metadata/MetadataWorker.kt

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.owncloud.android.operations.RefreshFolderOperation
1919
import kotlinx.coroutines.Dispatchers
2020
import kotlinx.coroutines.withContext
2121

22+
@Suppress("DEPRECATION", "ReturnCount", "TooGenericExceptionCaught")
2223
class MetadataWorker(private val context: Context, params: WorkerParameters, private val user: User) :
2324
CoroutineWorker(context, params) {
2425

@@ -27,36 +28,65 @@ class MetadataWorker(private val context: Context, params: WorkerParameters, pri
2728
const val FILE_PATH = "file_path"
2829
}
2930

30-
@Suppress("DEPRECATION", "ReturnCount")
3131
override suspend fun doWork(): Result {
32-
val storageManager = FileDataStorageManager(user, context.contentResolver)
3332
val filePath = inputData.getString(FILE_PATH)
3433
if (filePath == null) {
3534
Log_OC.e(TAG, "❌ Invalid folder path. Aborting metadata sync. $filePath")
3635
return Result.failure()
3736
}
37+
38+
val storageManager = FileDataStorageManager(user, context.contentResolver)
3839
val currentDir = storageManager.getFileByDecryptedRemotePath(filePath)
3940
if (currentDir == null) {
4041
Log_OC.e(TAG, "❌ Current directory is null. Aborting metadata sync. $filePath")
4142
return Result.failure()
4243
}
43-
Log_OC.d(TAG, "🕒 Starting metadata sync for folder: $filePath")
44+
if (!currentDir.hasValidParentId()) {
45+
Log_OC.e(TAG, "❌ Current directory has invalid ID: ${currentDir.fileId}. Path: $filePath")
46+
return Result.failure()
47+
}
48+
49+
Log_OC.d(TAG, "🕒 Starting metadata sync for folder: $filePath, id: ${currentDir.fileId}")
50+
51+
// First check current dir
52+
val currentRefreshResult = refreshFolder(currentDir, storageManager)
53+
if (!currentRefreshResult) {
54+
Log_OC.e(TAG, "❌ Failed to refresh current directory: $filePath")
55+
return Result.failure()
56+
}
4457

45-
// first check current dir
46-
refreshFolder(currentDir, storageManager)
58+
// Re-fetch the folder after refresh to get updated data
59+
val refreshedDir = storageManager.getFileByPath(filePath)
60+
if (refreshedDir == null || !refreshedDir.hasValidParentId()) {
61+
Log_OC.e(TAG, "❌ Directory invalid after refresh. Path: $filePath")
62+
return Result.failure()
63+
}
4764

4865
// then get up-to-date subfolders
49-
val subfolders = storageManager.getNonEncryptedSubfolders(currentDir.fileId, user.accountName)
66+
val subfolders = storageManager.getNonEncryptedSubfolders(refreshedDir.fileId, user.accountName)
67+
Log_OC.d(TAG, "Found ${subfolders.size} subfolders to sync")
68+
69+
var failedCount = 0
5070
subfolders.forEach { subFolder ->
51-
refreshFolder(subFolder, storageManager)
71+
if (!subFolder.hasValidParentId()) {
72+
Log_OC.e(TAG, "❌ Skipping subfolder with invalid ID: ${subFolder.remotePath}")
73+
failedCount++
74+
return@forEach
75+
}
76+
77+
val success = refreshFolder(subFolder, storageManager)
78+
if (!success) {
79+
failedCount++
80+
}
5281
}
5382

54-
Log_OC.d(TAG, "🏁 Metadata sync completed for folder: $filePath")
83+
Log_OC.d(TAG, "🏁 Metadata sync completed for folder: $filePath. Failed: $failedCount/${subfolders.size}")
84+
5585
return Result.success()
5686
}
5787

5888
@Suppress("DEPRECATION")
59-
private suspend fun refreshFolder(folder: OCFile, storageManager: FileDataStorageManager) =
89+
private suspend fun refreshFolder(folder: OCFile, storageManager: FileDataStorageManager): Boolean =
6090
withContext(Dispatchers.IO) {
6191
Log_OC.d(
6292
TAG,
@@ -65,19 +95,31 @@ class MetadataWorker(private val context: Context, params: WorkerParameters, pri
6595
" eTag: " + folder.etag + "\n" +
6696
" eTagOnServer: " + folder.etagOnServer
6797
)
98+
if (!folder.hasValidParentId()) {
99+
Log_OC.e(TAG, "❌ Folder has invalid ID: ${folder.remotePath}")
100+
return@withContext false
101+
}
102+
68103
if (!folder.isEtagChanged) {
69104
Log_OC.d(TAG, "Skipping ${folder.remotePath}, eTag didn't change")
70-
return@withContext
105+
return@withContext true
71106
}
72107

73-
Log_OC.d(TAG, "⏳ Fetching metadata for: ${folder.remotePath}")
108+
Log_OC.d(TAG, "⏳ Fetching metadata for: ${folder.remotePath}, id: ${folder.fileId}")
74109

75110
val operation = RefreshFolderOperation(folder, storageManager, user, context)
76-
val result = operation.execute(user, context)
77-
if (result.isSuccess) {
78-
Log_OC.d(TAG, "✅ Successfully fetched metadata for: ${folder.remotePath}")
79-
} else {
80-
Log_OC.e(TAG, "❌ Failed to fetch metadata for: ${folder.remotePath}")
111+
return@withContext try {
112+
val result = operation.execute(user, context)
113+
if (result.isSuccess) {
114+
Log_OC.d(TAG, "✅ Successfully fetched metadata for: ${folder.remotePath}")
115+
true
116+
} else {
117+
Log_OC.e(TAG, "❌ Failed to fetch metadata for: ${folder.remotePath}")
118+
false
119+
}
120+
} catch (e: Exception) {
121+
Log_OC.e(TAG, "❌ Exception refreshing folder ${folder.remotePath}: ${e.message}", e)
122+
false
81123
}
82124
}
83125
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,4 +1166,13 @@ public void setIsRecommendedFile(boolean value) {
11661166
public boolean isRecommendedFile() {
11671167
return recommendedFile;
11681168
}
1169+
1170+
// only root directories parent id can be 0
1171+
public boolean hasValidParentId() {
1172+
if (isRootDirectory()) {
1173+
return getParentId() == 0;
1174+
} else {
1175+
return getParentId() != 0;
1176+
}
1177+
}
11691178
}

0 commit comments

Comments
 (0)