Improved deletion and removed cancelledUploads Hashset

This commit is contained in:
Kanahia 2024-07-21 17:28:23 +05:30
parent 9f77fbbc8c
commit 283e2c0a63
11 changed files with 43 additions and 69 deletions

View file

@ -147,11 +147,6 @@ public class CommonsApplication extends MultiDexApplication {
*/ */
public static Map<String, Boolean> pauseUploads = new HashMap<>(); public static Map<String, Boolean> pauseUploads = new HashMap<>();
/**
* In-memory list of uploads that have been cancelled by the user
*/
public static HashSet<String> cancelledUploads = new HashSet<>();
/** /**
* Used to declare and initialize various components and dependencies * Used to declare and initialize various components and dependencies
*/ */

View file

@ -44,11 +44,19 @@ public abstract class ContributionDao {
@Delete @Delete
public abstract void deleteSynchronous(Contribution contribution); public abstract void deleteSynchronous(Contribution contribution);
@Delete
public abstract void deleteContributionsSynchronous(List<Contribution> contributions);
public Completable delete(final Contribution contribution) { public Completable delete(final Contribution contribution) {
return Completable return Completable
.fromAction(() -> deleteSynchronous(contribution)); .fromAction(() -> deleteSynchronous(contribution));
} }
public Completable deleteContributions(final List<Contribution> contributions) {
return Completable
.fromAction(() -> deleteContributionsSynchronous(contributions));
}
@Query("SELECT * from contribution WHERE media_filename=:fileName") @Query("SELECT * from contribution WHERE media_filename=:fileName")
public abstract List<Contribution> getContributionWithTitle(String fileName); public abstract List<Contribution> getContributionWithTitle(String fileName);

View file

@ -63,6 +63,10 @@ class ContributionsLocalDataSource {
return contributionDao.delete(contribution); return contributionDao.delete(contribution);
} }
public Completable deleteContributions(final List<Contribution> contributions) {
return contributionDao.deleteContributions(contributions);
}
public Factory<Integer, Contribution> getContributions() { public Factory<Integer, Contribution> getContributions() {
return contributionDao.fetchContributions(); return contributionDao.fetchContributions();
} }

View file

@ -36,6 +36,10 @@ public class ContributionsRepository {
return localDataSource.deleteContribution(contribution); return localDataSource.deleteContribution(contribution);
} }
public Completable deleteContributionsFromDB(List<Contribution> contributions) {
return localDataSource.deleteContributions(contributions);
}
/** /**
* Get contribution object with title * Get contribution object with title
* @param fileName * @param fileName

View file

@ -198,7 +198,6 @@ class FailedUploadsFragment : CommonsDaggerSupportFragment(), PendingUploadsCont
uploadProgressActivity.hidePendingIcons() uploadProgressActivity.hidePendingIcons()
pendingUploadsPresenter.deleteUploads( pendingUploadsPresenter.deleteUploads(
contributionsList, contributionsList,
0,
this.requireContext().applicationContext this.requireContext().applicationContext
) )
}, },

View file

@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.facebook.imagepipeline.request.ImageRequest import com.facebook.imagepipeline.request.ImageRequest
import fr.free.nrw.commons.R import fr.free.nrw.commons.R
import fr.free.nrw.commons.contributions.Contribution import fr.free.nrw.commons.contributions.Contribution
import timber.log.Timber
import java.io.File import java.io.File
@ -85,6 +86,7 @@ class PendingUploadsAdapter(private val callback: Callback) :
} }
fun bindState(state: Int) { fun bindState(state: Int) {
Timber.tag("PRINT").e("State is: "+state)
if (state == Contribution.STATE_QUEUED || state == Contribution.STATE_PAUSED) { if (state == Contribution.STATE_QUEUED || state == Contribution.STATE_PAUSED) {
errorTextView.text = "Queued" errorTextView.text = "Queued"
errorTextView.visibility = View.VISIBLE errorTextView.visibility = View.VISIBLE
@ -96,6 +98,7 @@ class PendingUploadsAdapter(private val callback: Callback) :
} }
fun bindProgress(transferred: Long, total: Long, state: Int) { fun bindProgress(transferred: Long, total: Long, state: Int) {
Timber.tag("PRINT").e("State is2: "+state)
if (transferred == 0L) { if (transferred == 0L) {
errorTextView.text = "Queued" errorTextView.text = "Queued"
errorTextView.visibility = View.VISIBLE errorTextView.visibility = View.VISIBLE

View file

@ -267,7 +267,6 @@ class PendingUploadsFragment : CommonsDaggerSupportFragment(), PendingUploadsCon
uploadProgressActivity.hidePendingIcons() uploadProgressActivity.hidePendingIcons()
pendingUploadsPresenter.deleteUploads( pendingUploadsPresenter.deleteUploads(
contributionsList, contributionsList,
0,
this.requireContext().applicationContext this.requireContext().applicationContext
) )
}, },

View file

@ -4,7 +4,6 @@ package fr.free.nrw.commons.upload;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
import androidx.paging.DataSource.Factory; import androidx.paging.DataSource.Factory;
import androidx.paging.LivePagedListBuilder; import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList; import androidx.paging.PagedList;
@ -136,18 +135,10 @@ public class PendingUploadsPresenter implements UserActionListener {
)); ));
} }
public void deleteUploads(List<Contribution> contributionList, int index, Context context) { public void deleteUploads(List<Contribution> contributionList, Context context) {
if (index >= contributionList.size()) {
return;
}
Contribution it = contributionList.get(index);
compositeDisposable.add(repository compositeDisposable.add(repository
.deleteContributionFromDB(it) .deleteContributionsFromDB(contributionList)
.subscribeOn(ioThreadScheduler) .subscribeOn(ioThreadScheduler)
.doOnComplete(() -> {
deleteUploads(contributionList, index + 1, context);
}
)
.subscribe(() -> .subscribe(() ->
WorkRequestHelper.Companion.makeOneTimeWorkRequest( WorkRequestHelper.Companion.makeOneTimeWorkRequest(
context, ExistingWorkPolicy.KEEP) context, ExistingWorkPolicy.KEEP)
@ -159,11 +150,11 @@ public class PendingUploadsPresenter implements UserActionListener {
return; return;
} }
Contribution it = contributionList.get(index); Contribution it = contributionList.get(index);
it.setState(Contribution.STATE_QUEUED); if (it.getErrorInfo() == null && it.getState() == Contribution.STATE_FAILED) {
if (it.getErrorInfo() == null){
it.setChunkInfo(null); it.setChunkInfo(null);
it.setTransferred(0); it.setTransferred(0);
} }
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(repository compositeDisposable.add(repository
.save(it) .save(it)
.subscribeOn(ioThreadScheduler) .subscribeOn(ioThreadScheduler)
@ -173,8 +164,8 @@ public class PendingUploadsPresenter implements UserActionListener {
} }
) )
.subscribe(() -> .subscribe(() ->
WorkRequestHelper.Companion.makeOneTimeWorkRequest( WorkRequestHelper.Companion.makeOneTimeWorkRequest(
context, ExistingWorkPolicy.KEEP), context, ExistingWorkPolicy.KEEP),
throwable -> { throwable -> {
Timber.e(throwable); Timber.e(throwable);
restartUploads(contributionList, index + 1, context); restartUploads(contributionList, index + 1, context);
@ -187,7 +178,7 @@ public class PendingUploadsPresenter implements UserActionListener {
return; return;
} }
Contribution it = contributionList.get(index); Contribution it = contributionList.get(index);
if (it.getErrorInfo() == null){ if (it.getErrorInfo() == null && it.getState() == Contribution.STATE_FAILED) {
it.setChunkInfo(null); it.setChunkInfo(null);
it.setTransferred(0); it.setTransferred(0);
} }
@ -196,8 +187,8 @@ public class PendingUploadsPresenter implements UserActionListener {
.save(it) .save(it)
.subscribeOn(ioThreadScheduler) .subscribeOn(ioThreadScheduler)
.subscribe(() -> .subscribe(() ->
WorkRequestHelper.Companion.makeOneTimeWorkRequest( WorkRequestHelper.Companion.makeOneTimeWorkRequest(
context, ExistingWorkPolicy.KEEP), context, ExistingWorkPolicy.KEEP),
throwable -> { throwable -> {
Timber.e(throwable); Timber.e(throwable);
} }

View file

@ -6,6 +6,7 @@ import fr.free.nrw.commons.CommonsApplication
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
import fr.free.nrw.commons.contributions.ChunkInfo import fr.free.nrw.commons.contributions.ChunkInfo
import fr.free.nrw.commons.contributions.Contribution import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.contributions.ContributionDao
import fr.free.nrw.commons.upload.worker.UploadWorker.NotificationUpdateProgressListener import fr.free.nrw.commons.upload.worker.UploadWorker.NotificationUpdateProgressListener
import fr.free.nrw.commons.wikidata.mwapi.MwException import fr.free.nrw.commons.wikidata.mwapi.MwException
import io.reactivex.Observable import io.reactivex.Observable
@ -33,7 +34,8 @@ class UploadClient @Inject constructor(
private val csrfTokenClient: CsrfTokenClient, private val csrfTokenClient: CsrfTokenClient,
private val pageContentsCreator: PageContentsCreator, private val pageContentsCreator: PageContentsCreator,
private val fileUtilsWrapper: FileUtilsWrapper, private val fileUtilsWrapper: FileUtilsWrapper,
private val gson: Gson, private val timeProvider: TimeProvider private val gson: Gson, private val timeProvider: TimeProvider,
private val contributionDao: ContributionDao
) { ) {
private val CHUNK_SIZE = 512 * 1024 // 512 KB private val CHUNK_SIZE = 512 * 1024 // 512 KB
@ -78,7 +80,7 @@ class UploadClient @Inject constructor(
compositeDisposable.add( compositeDisposable.add(
Observable.fromIterable(fileChunks).forEach { chunkFile: File -> Observable.fromIterable(fileChunks).forEach { chunkFile: File ->
if (canProcess(contribution, failures)) { if (canProcess(contribution, failures)) {
if (CommonsApplication.cancelledUploads.contains(contribution.pageId)) { if (contributionDao.getContribution(contribution.pageId) == null) {
compositeDisposable.clear() compositeDisposable.clear()
return@forEach return@forEach
} else { } else {
@ -101,7 +103,7 @@ class UploadClient @Inject constructor(
) )
return when { return when {
CommonsApplication.cancelledUploads.contains(contribution.pageId) -> { contributionDao.getContribution(contribution.pageId) == null -> {
return Observable.just(StashUploadResult(StashUploadState.CANCELLED, null, "Upload cancelled")) return Observable.just(StashUploadResult(StashUploadState.CANCELLED, null, "Upload cancelled"))
} }
contribution.isPaused() -> { contribution.isPaused() -> {

View file

@ -5,6 +5,7 @@ import dagger.Binds;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient; import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
import fr.free.nrw.commons.contributions.ContributionDao;
import fr.free.nrw.commons.di.NetworkingModule; import fr.free.nrw.commons.di.NetworkingModule;
import fr.free.nrw.commons.upload.categories.CategoriesContract; import fr.free.nrw.commons.upload.categories.CategoriesContract;
import fr.free.nrw.commons.upload.categories.CategoriesPresenter; import fr.free.nrw.commons.upload.categories.CategoriesPresenter;
@ -50,8 +51,8 @@ public abstract class UploadModule {
public static UploadClient provideUploadClient(final UploadInterface uploadInterface, public static UploadClient provideUploadClient(final UploadInterface uploadInterface,
@Named(NetworkingModule.NAMED_COMMONS_CSRF) final CsrfTokenClient csrfTokenClient, @Named(NetworkingModule.NAMED_COMMONS_CSRF) final CsrfTokenClient csrfTokenClient,
final PageContentsCreator pageContentsCreator, final FileUtilsWrapper fileUtilsWrapper, final PageContentsCreator pageContentsCreator, final FileUtilsWrapper fileUtilsWrapper,
final Gson gson) { final Gson gson, final ContributionDao contributionDao) {
return new UploadClient(uploadInterface, csrfTokenClient, pageContentsCreator, return new UploadClient(uploadInterface, csrfTokenClient, pageContentsCreator,
fileUtilsWrapper, gson, System::currentTimeMillis); fileUtilsWrapper, gson, System::currentTimeMillis, contributionDao);
} }
} }

View file

@ -213,32 +213,13 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
} }
queuedContributions.asFlow().map { contribution -> queuedContributions.asFlow().map { contribution ->
// Upload the contribution if it has not been cancelled by the user if (contributionDao.getContribution(contribution.pageId) != null) {
if (!CommonsApplication.cancelledUploads.contains(contribution.pageId)) { contribution.transferred = 0
/** contribution.state = Contribution.STATE_IN_PROGRESS
* If the limited connection mode is on, lets iterate through the queued contributionDao.saveSynchronous(contribution)
* contributions setProgressAsync(Data.Builder().putInt("progress", countUpload).build())
* and set the state as STATE_QUEUED_LIMITED_CONNECTION_MODE , countUpload++
* otherwise proceed with the upload uploadContribution(contribution = contribution)
*/
if (isLimitedConnectionModeEnabled()) {
if (contribution.state == Contribution.STATE_QUEUED) {
contribution.state = Contribution.STATE_QUEUED_LIMITED_CONNECTION_MODE
contributionDao.saveSynchronous(contribution)
}
} else {
contribution.transferred = 0
contribution.state = Contribution.STATE_IN_PROGRESS
contributionDao.saveSynchronous(contribution)
setProgressAsync(Data.Builder().putInt("progress", countUpload).build())
countUpload++
uploadContribution(contribution = contribution)
}
} else {
/* We can remove the cancelled upload from the hashset
as this contribution will not be processed again
*/
removeUploadFromInMemoryHashSet(contribution)
} }
}.collect() }.collect()
@ -259,13 +240,6 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
return Result.success() return Result.success()
} }
/**
* Removes the processed contribution from the cancelledUploads in-memory hashset
*/
private fun removeUploadFromInMemoryHashSet(contribution: Contribution) {
CommonsApplication.cancelledUploads.remove(contribution.pageId)
}
/** /**
* Create new notification for foreground service * Create new notification for foreground service
*/ */
@ -286,12 +260,6 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
.setContentTitle(appContext.getString(R.string.upload_in_progress)) .setContentTitle(appContext.getString(R.string.upload_in_progress))
.build() .build()
} }
/**
* Returns true is the limited connection mode is enabled
*/
private fun isLimitedConnectionModeEnabled(): Boolean {
return sessionManager.getPreference(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED)
}
/** /**
* Upload the contribution * Upload the contribution