@@ -19,14 +19,15 @@ import com.nextcloud.model.OfflineOperationType
1919import com.nextcloud.model.WorkerState
2020import com.nextcloud.model.WorkerStateLiveData
2121import com.owncloud.android.datamodel.FileDataStorageManager
22+ import com.owncloud.android.lib.common.OwnCloudClient
2223import com.owncloud.android.lib.common.operations.RemoteOperation
2324import com.owncloud.android.lib.common.operations.RemoteOperationResult
2425import com.owncloud.android.lib.common.utils.Log_OC
2526import com.owncloud.android.operations.CreateFolderOperation
2627import com.owncloud.android.utils.theme.ViewThemeUtils
2728import kotlinx.coroutines.Dispatchers
28- import kotlinx.coroutines.async
2929import kotlinx.coroutines.coroutineScope
30+ import kotlinx.coroutines.withContext
3031
3132class OfflineOperationsWorker (
3233 private val user : User ,
@@ -46,7 +47,7 @@ class OfflineOperationsWorker(
4647 private val notificationManager = OfflineOperationsNotificationManager (context, viewThemeUtils)
4748 private var repository = OfflineOperationsRepository (fileDataStorageManager)
4849
49- @Suppress(" TooGenericExceptionCaught" , " Deprecation " )
50+ @Suppress(" TooGenericExceptionCaught" )
5051 override suspend fun doWork (): Result = coroutineScope {
5152 val jobName = inputData.getString(JOB_NAME )
5253 Log_OC .d(
@@ -58,66 +59,82 @@ class OfflineOperationsWorker(
5859
5960 if (! connectivityService.isNetworkAndServerAvailable()) {
6061 Log_OC .d(TAG , " OfflineOperationsWorker cancelled, no internet connection" )
61- return @coroutineScope Result .success()
62- }
63-
64- val operations = fileDataStorageManager.offlineOperationDao.getAll()
65- if (operations.isEmpty()) {
66- Log_OC .d(TAG , " OfflineOperationsWorker cancelled, no offline operations were found" )
67- return @coroutineScope Result .success()
62+ return @coroutineScope Result .retry()
6863 }
6964
7065 val client = clientFactory.create(user)
71-
7266 notificationManager.start()
7367
74- operations.forEachIndexed { index, operation ->
75- val result = try {
76- if (operation.type == OfflineOperationType .CreateFolder && operation.parentPath != null ) {
77- val createFolderOperation = async(Dispatchers .IO ) {
68+ var operations = fileDataStorageManager.offlineOperationDao.getAll()
69+ val totalOperations = operations.size
70+ var currentOperationIndex = 0
71+
72+ return @coroutineScope try {
73+ while (operations.isNotEmpty()) {
74+ val operation = operations.first()
75+ val result = executeOperation(operation, client)
76+ handleResult(operation, totalOperations, currentOperationIndex, result?.first, result?.second)
77+
78+ currentOperationIndex++
79+ operations = fileDataStorageManager.offlineOperationDao.getAll()
80+ }
81+
82+ Log_OC .d(TAG , " OfflineOperationsWorker successfully completed" )
83+ notificationManager.dismissNotification()
84+ WorkerStateLiveData .instance().setWorkState(WorkerState .OfflineOperationsCompleted )
85+ Result .success()
86+ } catch (e: Exception ) {
87+ Log_OC .d(TAG , " OfflineOperationsWorker terminated: $e " )
88+ Result .failure()
89+ }
90+ }
91+
92+ @Suppress(" Deprecation" )
93+ private suspend fun executeOperation (
94+ operation : OfflineOperationEntity ,
95+ client : OwnCloudClient
96+ ): Pair <RemoteOperationResult <* >? , RemoteOperation<*>?>? {
97+ return when (operation.type) {
98+ OfflineOperationType .CreateFolder -> {
99+ if (operation.parentPath != null ) {
100+ val createFolderOperation = withContext(Dispatchers .IO ) {
78101 CreateFolderOperation (
79102 operation.path,
80103 user,
81104 context,
82105 fileDataStorageManager
83106 )
84- }.await()
85-
107+ }
86108 createFolderOperation.execute(client) to createFolderOperation
87109 } else {
88- Log_OC .d(TAG , " Operation terminated, not supported or incomplete operation " )
110+ Log_OC .d(TAG , " CreateFolder operation incomplete, missing parentPath " )
89111 null
90112 }
91- } catch (e: Exception ) {
92- Log_OC .d(TAG , " Operation terminated, exception caught: $e " )
93- null
94113 }
95114
96- handleResult(operation, operations, index, result?.first, result?.second)
115+ else -> {
116+ Log_OC .d(TAG , " Unsupported operation type: ${operation.type} " )
117+ null
118+ }
97119 }
98-
99- Log_OC .d(TAG , " OfflineOperationsWorker successfully completed" )
100- notificationManager.dismissNotification()
101- WorkerStateLiveData .instance().setWorkState(WorkerState .OfflineOperationsCompleted )
102- return @coroutineScope Result .success()
103120 }
104121
105122 private fun handleResult (
106123 operation : OfflineOperationEntity ,
107- operations : List < OfflineOperationEntity > ,
124+ totalOperations : Int ,
108125 currentOperationIndex : Int ,
109126 result : RemoteOperationResult <* >? ,
110127 remoteOperation : RemoteOperation <* >?
111128 ) {
112129 result ? : return Log_OC .d(TAG , " Operation not completed, result is null" )
113130
114- val logMessage = if (result.isSuccess) " Operation completed" else " Operation terminated "
131+ val logMessage = if (result.isSuccess) " Operation completed" else " Operation failed "
115132 Log_OC .d(TAG , " $logMessage path: ${operation.path} , type: ${operation.type} " )
116133
117134 if (result.isSuccess) {
118135 repository.updateNextOperations(operation)
119136 fileDataStorageManager.offlineOperationDao.delete(operation)
120- notificationManager.update(operations.size , currentOperationIndex, operation.filename ? : " " )
137+ notificationManager.update(totalOperations , currentOperationIndex, operation.filename ? : " " )
121138 } else {
122139 val excludedErrorCodes = listOf (RemoteOperationResult .ResultCode .FOLDER_ALREADY_EXISTS )
123140
0 commit comments