Skip to content

Commit dce5c99

Browse files
committed
fix: git conflict
Signed-off-by: alperozturk <[email protected]>
1 parent 69c6db4 commit dce5c99

File tree

2 files changed

+104
-57
lines changed

2 files changed

+104
-57
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ interface UploadDao {
7171
)
7272
suspend fun updateStatus(remotePath: String, accountName: String, status: Int): Int
7373

74+
@Query(
75+
"""
76+
SELECT * FROM ${ProviderTableMeta.UPLOADS_TABLE_NAME}
77+
WHERE ${ProviderTableMeta.UPLOADS_STATUS} = :status
78+
AND (:nameCollisionPolicy IS NULL OR ${ProviderTableMeta.UPLOADS_NAME_COLLISION_POLICY} = :nameCollisionPolicy)
79+
"""
80+
)
81+
suspend fun getUploadsByStatus(status: Int, nameCollisionPolicy: Int? = null): List<UploadEntity>
82+
7483
@Query(
7584
"""
7685
SELECT * FROM ${ProviderTableMeta.UPLOADS_TABLE_NAME}
@@ -79,7 +88,7 @@ interface UploadDao {
7988
AND (:nameCollisionPolicy IS NULL OR ${ProviderTableMeta.UPLOADS_NAME_COLLISION_POLICY} = :nameCollisionPolicy)
8089
"""
8190
)
82-
suspend fun getUploadsByStatus(
91+
suspend fun getUploadsByAccountNameAndStatus(
8392
accountName: String,
8493
status: Int,
8594
nameCollisionPolicy: Int? = null

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

Lines changed: 94 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -88,33 +88,57 @@ class FileUploadHelper {
8888
fun buildRemoteName(accountName: String, remotePath: String): String = accountName + remotePath
8989
}
9090

91+
/**
92+
* Retries all failed uploads across all user accounts.
93+
*
94+
* This function retrieves all uploads with the status [UploadStatus.UPLOAD_FAILED], including both
95+
* manual uploads and auto uploads. It runs in a background thread (Dispatcher.IO) and ensures
96+
* that only one retry operation runs at a time by using a semaphore to prevent concurrent execution.
97+
*
98+
* Once the failed uploads are retrieved, it calls [retryUploads], which triggers the corresponding
99+
* upload workers for each failed upload.
100+
*
101+
* The function returns `true` if there were any failed uploads to retry and the retry process was
102+
* started, or `false` if no uploads were retried.
103+
*
104+
* @param uploadsStorageManager Provides access to upload data and persistence.
105+
* @param connectivityService Checks the current network connectivity state.
106+
* @param accountManager Handles user account authentication and selection.
107+
* @param powerManagementService Ensures uploads respect power constraints.
108+
* @return `true` if any failed uploads were found and retried; `false` otherwise.
109+
*/
91110
fun retryFailedUploads(
92111
uploadsStorageManager: UploadsStorageManager,
93112
connectivityService: ConnectivityService,
94113
accountManager: UserAccountManager,
95114
powerManagementService: PowerManagementService
96-
) {
97-
if (retryFailedUploadsSemaphore.tryAcquire()) {
98-
try {
99-
val failedUploads = uploadsStorageManager.failedUploads
100-
if (failedUploads == null || failedUploads.isEmpty()) {
101-
Log_OC.d(TAG, "Failed uploads are empty or null")
102-
return
115+
): Boolean {
116+
if (!retryFailedUploadsSemaphore.tryAcquire()) {
117+
Log_OC.d(TAG, "skipping retryFailedUploads, already running")
118+
return true
119+
}
120+
121+
var isUploadStarted = false
122+
123+
try {
124+
getUploadsByStatus(null, UploadStatus.UPLOAD_FAILED) {
125+
if (it.isNotEmpty()) {
126+
isUploadStarted = true
103127
}
104128

105129
retryUploads(
106130
uploadsStorageManager,
107131
connectivityService,
108132
accountManager,
109133
powerManagementService,
110-
failedUploads
134+
uploads = it
111135
)
112-
} finally {
113-
retryFailedUploadsSemaphore.release()
114136
}
115-
} else {
116-
Log_OC.d(TAG, "Skip retryFailedUploads since it is already running")
137+
} finally {
138+
retryFailedUploadsSemaphore.release()
117139
}
140+
141+
return isUploadStarted
118142
}
119143

120144
fun retryCancelledUploads(
@@ -123,18 +147,18 @@ class FileUploadHelper {
123147
accountManager: UserAccountManager,
124148
powerManagementService: PowerManagementService
125149
): Boolean {
126-
val cancelledUploads = uploadsStorageManager.cancelledUploadsForCurrentAccount
127-
if (cancelledUploads == null || cancelledUploads.isEmpty()) {
128-
return false
150+
var result = false
151+
getUploadsByStatus(accountManager.user.accountName, UploadStatus.UPLOAD_CANCELLED) {
152+
result = retryUploads(
153+
uploadsStorageManager,
154+
connectivityService,
155+
accountManager,
156+
powerManagementService,
157+
it
158+
)
129159
}
130160

131-
return retryUploads(
132-
uploadsStorageManager,
133-
connectivityService,
134-
accountManager,
135-
powerManagementService,
136-
cancelledUploads
137-
)
161+
return result
138162
}
139163

140164
@Suppress("ComplexCondition")
@@ -143,51 +167,51 @@ class FileUploadHelper {
143167
connectivityService: ConnectivityService,
144168
accountManager: UserAccountManager,
145169
powerManagementService: PowerManagementService,
146-
failedUploads: Array<OCUpload>
170+
uploads: Array<OCUpload>
147171
): Boolean {
148172
var showNotExistMessage = false
149173
val isOnline = checkConnectivity(connectivityService)
150174
val connectivity = connectivityService.connectivity
151175
val batteryStatus = powerManagementService.battery
152-
val accountNames = accountManager.accounts.filter { account ->
153-
accountManager.getUser(account.name).isPresent
154-
}.map { account ->
155-
account.name
156-
}.toHashSet()
157-
158-
for (failedUpload in failedUploads) {
159-
if (!accountNames.contains(failedUpload.accountName)) {
160-
uploadsStorageManager.removeUpload(failedUpload)
161-
continue
162-
}
163176

164-
val uploadResult =
165-
checkUploadConditions(failedUpload, connectivity, batteryStatus, powerManagementService, isOnline)
177+
val uploadsToRetry = mutableListOf<Long>()
178+
179+
for (upload in uploads) {
180+
val uploadResult = checkUploadConditions(
181+
upload,
182+
connectivity,
183+
batteryStatus,
184+
powerManagementService,
185+
isOnline
186+
)
166187

167188
if (uploadResult != UploadResult.UPLOADED) {
168-
if (failedUpload.lastResult != uploadResult) {
189+
if (upload.lastResult != uploadResult) {
169190
// Setting Upload status else cancelled uploads will behave wrong, when retrying
170191
// Needs to happen first since lastResult wil be overwritten by setter
171-
failedUpload.uploadStatus = UploadStatus.UPLOAD_FAILED
192+
upload.uploadStatus = UploadStatus.UPLOAD_FAILED
172193

173-
failedUpload.lastResult = uploadResult
174-
uploadsStorageManager.updateUpload(failedUpload)
194+
upload.lastResult = uploadResult
195+
uploadsStorageManager.updateUpload(upload)
175196
}
176197
if (uploadResult == UploadResult.FILE_NOT_FOUND) {
177198
showNotExistMessage = true
178199
}
179200
continue
180201
}
181202

182-
failedUpload.uploadStatus = UploadStatus.UPLOAD_IN_PROGRESS
183-
uploadsStorageManager.updateUpload(failedUpload)
203+
// Only uploads that passed checks get marked in progress and are collected for scheduling
204+
upload.uploadStatus = UploadStatus.UPLOAD_IN_PROGRESS
205+
uploadsStorageManager.updateUpload(upload)
206+
uploadsToRetry.add(upload.uploadId)
184207
}
185208

186-
accountNames.forEach { accountName ->
187-
val user = accountManager.getUser(accountName)
188-
if (user.isPresent) {
189-
backgroundJobManager.startFilesUploadJob(user.get(), failedUploads.getUploadIds(), false)
190-
}
209+
if (uploadsToRetry.isNotEmpty()) {
210+
backgroundJobManager.startFilesUploadJob(
211+
accountManager.user,
212+
uploadsToRetry.toLongArray(),
213+
false
214+
)
191215
}
192216

193217
return showNotExistMessage
@@ -235,21 +259,35 @@ class FileUploadHelper {
235259
}
236260
}
237261

262+
/**
263+
* Retrieves uploads filtered by their status, optionally for a specific account.
264+
*
265+
* This function queries the uploads database asynchronously to obtain a list of uploads
266+
* that match the specified [status]. If an [accountName] is provided, only uploads
267+
* belonging to that account are retrieved. If [accountName] is `null`, uploads with the
268+
* given [status] from **all user accounts** are returned.
269+
*
270+
* Once the uploads are fetched, the [onCompleted] callback is invoked with the resulting array.
271+
*
272+
* @param accountName The name of the account to filter uploads by.
273+
* If `null`, uploads matching the given [status] from all accounts are returned.
274+
* @param status The [UploadStatus] to filter uploads by (e.g., `UPLOAD_FAILED`).
275+
* @param nameCollisionPolicy The [NameCollisionPolicy] to filter uploads by (e.g., `SKIP`).
276+
* @param onCompleted A callback invoked with the resulting array of [OCUpload] objects.
277+
*/
238278
fun getUploadsByStatus(
239-
accountName: String,
279+
accountName: String?,
240280
status: UploadStatus,
241281
nameCollisionPolicy: NameCollisionPolicy? = null,
242282
onCompleted: (Array<OCUpload>) -> Unit
243283
) {
244284
ioScope.launch {
245-
val result = uploadsStorageManager.uploadDao
246-
.getUploadsByStatus(
247-
accountName,
248-
status.value,
249-
nameCollisionPolicy?.serialize()
250-
)
251-
.map { it.toOCUpload(null) }
252-
.toTypedArray()
285+
val dao = uploadsStorageManager.uploadDao
286+
val result = if (accountName != null) {
287+
dao.getUploadsByAccountNameAndStatus(accountName, status.value, nameCollisionPolicy?.serialize())
288+
} else {
289+
dao.getUploadsByStatus(status.value, nameCollisionPolicy?.serialize())
290+
}.map { it.toOCUpload(null) }.toTypedArray()
253291
onCompleted(result)
254292
}
255293
}

0 commit comments

Comments
 (0)