Skip to content

Commit dbe1f7d

Browse files
committed
fix: retryFailedUploads calls
Signed-off-by: alperozturk <[email protected]>
1 parent 71209dd commit dbe1f7d

File tree

5 files changed

+79
-52
lines changed

5 files changed

+79
-52
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,11 @@ interface UploadDao {
7676
"WHERE ${ProviderTableMeta.UPLOADS_ACCOUNT_NAME} = :accountName " +
7777
"AND ${ProviderTableMeta.UPLOADS_STATUS} = :status"
7878
)
79-
suspend fun getUploadsByStatus(accountName: String, status: Int): List<UploadEntity>
79+
suspend fun getUploadsByAccountAndStatus(accountName: String, status: Int): List<UploadEntity>
80+
81+
@Query(
82+
"SELECT * FROM ${ProviderTableMeta.UPLOADS_TABLE_NAME} " +
83+
"WHERE ${ProviderTableMeta.UPLOADS_STATUS} = :status"
84+
)
85+
suspend fun getUploadsByStatus(status: Int): List<UploadEntity>
8086
}

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

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,29 +88,71 @@ class FileUploadHelper {
8888
fun buildRemoteName(accountName: String, remotePath: String): String = accountName + remotePath
8989
}
9090

91-
fun getUploadsByStatus(accountName: String, status: UploadStatus, onCompleted: (Array<OCUpload>) -> Unit) {
91+
/**
92+
* Retrieves uploads filtered by their status, optionally for a specific account.
93+
*
94+
* This function queries the uploads database asynchronously to obtain a list of uploads
95+
* that match the specified [status]. If an [accountName] is provided, only uploads
96+
* belonging to that account are retrieved. If [accountName] is `null`, uploads with the
97+
* given [status] from **all user accounts** are returned.
98+
*
99+
* Once the uploads are fetched, the [onCompleted] callback is invoked with the resulting array.
100+
*
101+
* @param accountName The name of the account to filter uploads by.
102+
* If `null`, uploads matching the given [status] from all accounts are returned.
103+
* @param status The [UploadStatus] to filter uploads by (e.g., `UPLOAD_FAILED`).
104+
* @param onCompleted A callback invoked with the resulting array of [OCUpload] objects.
105+
*/
106+
fun getUploadsByStatus(accountName: String?, status: UploadStatus, onCompleted: (Array<OCUpload>) -> Unit) {
92107
ioScope.launch {
93-
val result = uploadsStorageManager.uploadDao.getUploadsByStatus(
94-
accountName,
95-
status.value
96-
).map { it.toOCUpload(null) }.toTypedArray()
108+
val dao = uploadsStorageManager.uploadDao
109+
val result = if (accountName != null) {
110+
dao.getUploadsByAccountAndStatus(accountName, status.value)
111+
} else {
112+
dao.getUploadsByStatus(status.value)
113+
}.map { it.toOCUpload(null) }.toTypedArray()
97114
onCompleted(result)
98115
}
99116
}
100117

118+
/**
119+
* Retries all failed uploads across all user accounts.
120+
*
121+
* This function retrieves all uploads with the status [UploadStatus.UPLOAD_FAILED], including both
122+
* manual uploads and auto uploads. It runs in a background thread (Dispatcher.IO) and ensures
123+
* that only one retry operation runs at a time by using a semaphore to prevent concurrent execution.
124+
*
125+
* Once the failed uploads are retrieved, it calls [retryUploads], which triggers the corresponding
126+
* upload workers for each failed upload.
127+
*
128+
* The function returns `true` if there were any failed uploads to retry and the retry process was
129+
* started, or `false` if no uploads were retried.
130+
*
131+
* @param uploadsStorageManager Provides access to upload data and persistence.
132+
* @param connectivityService Checks the current network connectivity state.
133+
* @param accountManager Handles user account authentication and selection.
134+
* @param powerManagementService Ensures uploads respect power constraints.
135+
* @return `true` if any failed uploads were found and retried; `false` otherwise.
136+
*/
101137
fun retryFailedUploads(
102138
uploadsStorageManager: UploadsStorageManager,
103139
connectivityService: ConnectivityService,
104140
accountManager: UserAccountManager,
105141
powerManagementService: PowerManagementService
106-
) {
142+
): Boolean {
107143
if (!retryFailedUploadsSemaphore.tryAcquire()) {
108144
Log_OC.d(TAG, "skipping retryFailedUploads, already running")
109-
return
145+
return true
110146
}
111147

148+
var isUploadStarted = false
149+
112150
try {
113-
getUploadsByStatus(accountManager.user.accountName, UploadStatus.UPLOAD_FAILED) {
151+
getUploadsByStatus(null, UploadStatus.UPLOAD_FAILED) {
152+
if (it.isNotEmpty()) {
153+
isUploadStarted = true
154+
}
155+
114156
retryUploads(
115157
uploadsStorageManager,
116158
connectivityService,
@@ -122,6 +164,8 @@ class FileUploadHelper {
122164
} finally {
123165
retryFailedUploadsSemaphore.release()
124166
}
167+
168+
return isUploadStarted
125169
}
126170

127171
fun retryCancelledUploads(

app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import com.owncloud.android.datamodel.OCFile;
3636
import com.owncloud.android.datamodel.SyncedFolderProvider;
3737
import com.owncloud.android.datamodel.UploadsStorageManager;
38-
import com.owncloud.android.db.OCUpload;
3938
import com.owncloud.android.lib.common.operations.RemoteOperation;
4039
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
4140
import com.owncloud.android.lib.common.utils.Log_OC;
@@ -51,8 +50,6 @@
5150
import androidx.recyclerview.widget.GridLayoutManager;
5251
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
5352
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
54-
import kotlin.Unit;
55-
import kotlin.jvm.functions.Function1;
5653

5754
/**
5855
* Activity listing pending, active, and completed uploads. User can delete completed uploads from view. Content of this
@@ -136,15 +133,13 @@ private void observeWorkerState() {
136133
WorkerStateLiveData.Companion.instance().observe(this, state -> {
137134
if (state instanceof WorkerState.UploadStarted) {
138135
Log_OC.d(TAG, "Upload worker started");
139-
handleUploadWorkerState();
136+
uploadListAdapter.loadUploadItemsFromDb();
137+
} else if (state instanceof WorkerState.UploadFinished) {
138+
uploadListAdapter.loadUploadItemsFromDb(() -> swipeListRefreshLayout.setRefreshing(false));
140139
}
141140
});
142141
}
143142

144-
private void handleUploadWorkerState() {
145-
uploadListAdapter.loadUploadItemsFromDb();
146-
}
147-
148143
private void setupContent() {
149144
binding.list.setEmptyView(binding.emptyList.getRoot());
150145
binding.emptyList.getRoot().setVisibility(View.GONE);
@@ -185,28 +180,15 @@ private void loadItems() {
185180
}
186181

187182
private void refresh() {
188-
FilesSyncHelper.startAutoUploadImmediately(syncedFolderProvider,
189-
backgroundJobManager,
190-
true);
191-
192-
FileUploadHelper.Companion.instance().getUploadsByStatus(accountManager.getUser().getAccountName(), UploadsStorageManager.UploadStatus.UPLOAD_FAILED, new Function1<>() {
193-
@Override
194-
public Unit invoke(OCUpload[] ocUploads) {
195-
new Thread(() -> {
196-
FileUploadHelper.Companion.instance().retryFailedUploads(
197-
uploadsStorageManager,
198-
connectivityService,
199-
accountManager,
200-
powerManagementService);
201-
uploadListAdapter.loadUploadItemsFromDb();
202-
}).start();
203-
DisplayUtils.showSnackMessage(UploadListActivity.this, R.string.uploader_local_files_uploaded);
204-
return Unit.INSTANCE;
205-
}
206-
});
207-
208-
// update UI
209-
uploadListAdapter.loadUploadItemsFromDb(() -> swipeListRefreshLayout.setRefreshing(false));
183+
boolean isUploadStarted = FileUploadHelper.Companion.instance().retryFailedUploads(
184+
uploadsStorageManager,
185+
connectivityService,
186+
accountManager,
187+
powerManagementService);
188+
189+
if (!isUploadStarted) {
190+
uploadListAdapter.loadUploadItemsFromDb(() -> swipeListRefreshLayout.setRefreshing(false));
191+
}
210192
}
211193

212194
@Override

app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,16 +250,12 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) {
250250
clearTempEncryptedFolder();
251251
loadUploadItemsFromDb();
252252
} else if (itemId == R.id.action_upload_list_failed_retry) {
253-
254-
// FIXME For e2e resume is not working
255-
new Thread(() -> {
256-
uploadHelper.retryFailedUploads(
257-
uploadsStorageManager,
258-
connectivityService,
259-
accountManager,
260-
powerManagementService);
261-
loadUploadItemsFromDb();
262-
}).start();
253+
uploadHelper.retryFailedUploads(
254+
uploadsStorageManager,
255+
connectivityService,
256+
accountManager,
257+
powerManagementService);
258+
loadUploadItemsFromDb();
263259
}
264260

265261
return true;

app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.nextcloud.client.network.ConnectivityService;
2525
import com.nextcloud.utils.extensions.UriExtensionsKt;
2626
import com.owncloud.android.MainApp;
27-
import com.owncloud.android.datamodel.FileDataStorageManager;
2827
import com.owncloud.android.datamodel.FilesystemDataProvider;
2928
import com.owncloud.android.datamodel.MediaFolderType;
3029
import com.owncloud.android.datamodel.SyncedFolder;
@@ -222,11 +221,11 @@ public static void restartUploadsIfNeeded(final UploadsStorageManager uploadsSto
222221
final ConnectivityService connectivityService,
223222
final PowerManagementService powerManagementService) {
224223
Log_OC.d(TAG, "restartUploadsIfNeeded, called");
225-
new Thread(() -> FileUploadHelper.Companion.instance().retryFailedUploads(
224+
FileUploadHelper.Companion.instance().retryFailedUploads(
226225
uploadsStorageManager,
227226
connectivityService,
228227
accountManager,
229-
powerManagementService)).start();
228+
powerManagementService);
230229
}
231230

232231
public static void scheduleFilesSyncForAllFoldersIfNeeded(Context context, SyncedFolderProvider syncedFolderProvider, BackgroundJobManager jobManager) {

0 commit comments

Comments
 (0)