Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ interface FileDao {
AND file_owner = :accountName
AND is_encrypted = 0
AND (content_type = :dirType OR content_type = :webdavType)
ORDER BY ${ProviderTableMeta.FILE_DEFAULT_SORT_ORDER}
ORDER BY ${ProviderTableMeta._ID} ASC
"""
)
fun getNonEncryptedSubfolders(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.owncloud.android.operations.RefreshFolderOperation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

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

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

@Suppress("DEPRECATION", "ReturnCount")
override suspend fun doWork(): Result {
val storageManager = FileDataStorageManager(user, context.contentResolver)
val filePath = inputData.getString(FILE_PATH)
if (filePath == null) {
Log_OC.e(TAG, "❌ Invalid folder path. Aborting metadata sync. $filePath")
return Result.failure()
}

val storageManager = FileDataStorageManager(user, context.contentResolver)
val currentDir = storageManager.getFileByDecryptedRemotePath(filePath)
if (currentDir == null) {
Log_OC.e(TAG, "❌ Current directory is null. Aborting metadata sync. $filePath")
return Result.failure()
}
Log_OC.d(TAG, "🕒 Starting metadata sync for folder: $filePath")
if (!currentDir.hasValidParentId()) {
Log_OC.e(TAG, "❌ Current directory has invalid ID: ${currentDir.fileId}. Path: $filePath")
return Result.failure()
}

Log_OC.d(TAG, "🕒 Starting metadata sync for folder: $filePath, id: ${currentDir.fileId}")

// First check current dir
val currentRefreshResult = refreshFolder(currentDir, storageManager)
if (!currentRefreshResult) {
Log_OC.e(TAG, "❌ Failed to refresh current directory: $filePath")
return Result.failure()
}

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

// then get up-to-date subfolders
val subfolders = storageManager.getNonEncryptedSubfolders(currentDir.fileId, user.accountName)
val subfolders = storageManager.getNonEncryptedSubfolders(refreshedDir.fileId, user.accountName)
Log_OC.d(TAG, "Found ${subfolders.size} subfolders to sync")

var failedCount = 0
subfolders.forEach { subFolder ->
refreshFolder(subFolder, storageManager)
if (!subFolder.hasValidParentId()) {
Log_OC.e(TAG, "❌ Skipping subfolder with invalid ID: ${subFolder.remotePath}")
failedCount++
return@forEach
}

val success = refreshFolder(subFolder, storageManager)
if (!success) {
failedCount++
}
}

Log_OC.d(TAG, "🏁 Metadata sync completed for folder: $filePath")
Log_OC.d(TAG, "🏁 Metadata sync completed for folder: $filePath. Failed: $failedCount/${subfolders.size}")

return Result.success()
}

@Suppress("DEPRECATION")
private suspend fun refreshFolder(folder: OCFile, storageManager: FileDataStorageManager) =
private suspend fun refreshFolder(folder: OCFile, storageManager: FileDataStorageManager): Boolean =
withContext(Dispatchers.IO) {
Log_OC.d(
TAG,
Expand All @@ -65,19 +95,31 @@ class MetadataWorker(private val context: Context, params: WorkerParameters, pri
" eTag: " + folder.etag + "\n" +
" eTagOnServer: " + folder.etagOnServer
)
if (!folder.hasValidParentId()) {
Log_OC.e(TAG, "❌ Folder has invalid ID: ${folder.remotePath}")
return@withContext false
}

if (!folder.isEtagChanged) {
Log_OC.d(TAG, "Skipping ${folder.remotePath}, eTag didn't change")
return@withContext
return@withContext true
}

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

val operation = RefreshFolderOperation(folder, storageManager, user, context)
val result = operation.execute(user, context)
if (result.isSuccess) {
Log_OC.d(TAG, "✅ Successfully fetched metadata for: ${folder.remotePath}")
} else {
Log_OC.e(TAG, "❌ Failed to fetch metadata for: ${folder.remotePath}")
return@withContext try {
val result = operation.execute(user, context)
if (result.isSuccess) {
Log_OC.d(TAG, "✅ Successfully fetched metadata for: ${folder.remotePath}")
true
} else {
Log_OC.e(TAG, "❌ Failed to fetch metadata for: ${folder.remotePath}")
false
}
} catch (e: Exception) {
Log_OC.e(TAG, "❌ Exception refreshing folder ${folder.remotePath}: ${e.message}", e)
false
}
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/com/owncloud/android/datamodel/OCFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -1166,4 +1166,13 @@ public void setIsRecommendedFile(boolean value) {
public boolean isRecommendedFile() {
return recommendedFile;
}

// only root directories parent id can be 0
public boolean hasValidParentId() {
if (isRootDirectory()) {
return getParentId() == 0;
} else {
return getParentId() != 0;
}
}
}
Loading