Added image duplicity check on restart of failed image

This commit is contained in:
Kanahia 2024-07-31 17:45:43 +05:30
parent ae00a9d19f
commit e96cc8b5ca
6 changed files with 135 additions and 47 deletions

View file

@ -5,6 +5,7 @@ import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED;
import static fr.free.nrw.commons.contributions.Contribution.STATE_PAUSED;
import static fr.free.nrw.commons.nearby.fragments.NearbyParentFragment.WLM_URL;
import static fr.free.nrw.commons.profile.ProfileActivity.KEY_USERNAME;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
import static fr.free.nrw.commons.utils.LengthUtils.computeBearing;
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
@ -831,10 +832,18 @@ public class ContributionsFragment
* @param contribution
*/
public void restartUpload(Contribution contribution) {
contribution.setState(Contribution.STATE_QUEUED);
contribution.setDateUploadStarted(Calendar.getInstance().getTime());
contributionsPresenter.saveContribution(contribution);
Timber.d("Restarting for %s", contribution.toString());
if (contribution.getState() == Contribution.STATE_FAILED) {
if (contribution.getErrorInfo() == null){
contribution.setChunkInfo(null);
contribution.setTransferred(0);
}
contributionsPresenter.checkDuplicateImageAndRestartContribution(contribution);
} else {
contribution.setState(Contribution.STATE_QUEUED);
contributionsPresenter.saveContribution(contribution);
Timber.d("Restarting for %s", contribution.toString());
}
}
/**
@ -856,10 +865,6 @@ public class ContributionsFragment
contribution.setRetries(retries + 1);
Timber.d("Retried uploading %s %d times", contribution.getMedia().getFilename(),
retries + 1);
if (contribution.getErrorInfo() == null){
contribution.setChunkInfo(null);
contribution.setTransferred(0);
}
restartUpload(contribution);
} else {
// TODO: Show the exact reason for failure

View file

@ -1,21 +1,26 @@
package fr.free.nrw.commons.contributions;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
import androidx.work.ExistingWorkPolicy;
import fr.free.nrw.commons.MediaDataExtractor;
import fr.free.nrw.commons.contributions.ContributionsContract.UserActionListener;
import fr.free.nrw.commons.di.CommonsApplicationModule;
import fr.free.nrw.commons.repository.UploadRepository;
import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
import io.reactivex.Scheduler;
import io.reactivex.disposables.CompositeDisposable;
import javax.inject.Inject;
import javax.inject.Named;
import timber.log.Timber;
/**
* The presenter class for Contributions
*/
public class ContributionsPresenter implements UserActionListener {
private final ContributionsRepository repository;
private final ContributionsRepository contributionsRepository;
private final UploadRepository uploadRepository;
private final Scheduler ioThreadScheduler;
private CompositeDisposable compositeDisposable;
private ContributionsContract.View view;
@ -25,8 +30,10 @@ public class ContributionsPresenter implements UserActionListener {
@Inject
ContributionsPresenter(ContributionsRepository repository,
UploadRepository uploadRepository,
@Named(CommonsApplicationModule.IO_THREAD) Scheduler ioThreadScheduler) {
this.repository = repository;
this.contributionsRepository = repository;
this.uploadRepository = uploadRepository;
this.ioThreadScheduler=ioThreadScheduler;
}
@ -44,7 +51,25 @@ public class ContributionsPresenter implements UserActionListener {
@Override
public Contribution getContributionsWithTitle(String title) {
return repository.getContributionWithFileName(title);
return contributionsRepository.getContributionWithFileName(title);
}
public void checkDuplicateImageAndRestartContribution(Contribution contribution){
compositeDisposable.add(uploadRepository
.checkDuplicateImage(contribution.getLocalUriPath().getPath())
.subscribeOn(ioThreadScheduler)
.subscribe(imageCheckResult -> {
if (imageCheckResult == IMAGE_OK) {
contribution.setState(Contribution.STATE_QUEUED);
saveContribution(contribution);
}else {
Timber.e("Contribution already exists");
compositeDisposable.add(contributionsRepository
.deleteContributionFromDB(contribution)
.subscribeOn(ioThreadScheduler)
.subscribe());
}
}));
}
/**
@ -54,7 +79,7 @@ public class ContributionsPresenter implements UserActionListener {
* @param contribution
*/
public void saveContribution(Contribution contribution) {
compositeDisposable.add(repository
compositeDisposable.add(contributionsRepository
.save(contribution)
.subscribeOn(ioThreadScheduler)
.subscribe(() -> WorkRequestHelper.Companion.makeOneTimeWorkRequest(

View file

@ -203,6 +203,16 @@ public class UploadRepository {
return uploadModel.getImageQuality(uploadItem, location);
}
/**
* query the RemoteDataSource for image duplicity check
*
* @param filePath file to be checked
* @return IMAGE_DUPLICATE or IMAGE_OK
*/
public Single<Integer> checkDuplicateImage(String filePath) {
return uploadModel.checkDuplicateImage(filePath);
}
/**
* query the RemoteDataSource for caption quality
*

View file

@ -140,7 +140,7 @@ public class ImageProcessingService {
* @param filePath file to be checked
* @return IMAGE_DUPLICATE or IMAGE_OK
*/
private Single<Integer> checkDuplicateImage(String filePath) {
Single<Integer> checkDuplicateImage(String filePath) {
Timber.d("Checking for duplicate image %s", filePath);
return Single.fromCallable(() -> fileUtilsWrapper.getFileInputStream(filePath))
.map(fileUtilsWrapper::getSHA1)

View file

@ -1,6 +1,8 @@
package fr.free.nrw.commons.upload;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
@ -14,6 +16,7 @@ import fr.free.nrw.commons.contributions.ContributionBoundaryCallback;
import fr.free.nrw.commons.contributions.ContributionsRemoteDataSource;
import fr.free.nrw.commons.contributions.ContributionsRepository;
import fr.free.nrw.commons.di.CommonsApplicationModule;
import fr.free.nrw.commons.repository.UploadRepository;
import fr.free.nrw.commons.upload.PendingUploadsContract.UserActionListener;
import fr.free.nrw.commons.upload.PendingUploadsContract.View;
import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
@ -33,7 +36,8 @@ import timber.log.Timber;
public class PendingUploadsPresenter implements UserActionListener {
private final ContributionBoundaryCallback contributionBoundaryCallback;
private final ContributionsRepository repository;
private final ContributionsRepository contributionsRepository;
private final UploadRepository uploadRepository;
private final Scheduler ioThreadScheduler;
private final CompositeDisposable compositeDisposable;
@ -46,10 +50,12 @@ public class PendingUploadsPresenter implements UserActionListener {
PendingUploadsPresenter(
final ContributionBoundaryCallback contributionBoundaryCallback,
final ContributionsRemoteDataSource contributionsRemoteDataSource,
final ContributionsRepository repository,
final ContributionsRepository contributionsRepository,
final UploadRepository uploadRepository,
@Named(CommonsApplicationModule.IO_THREAD) final Scheduler ioThreadScheduler) {
this.contributionBoundaryCallback = contributionBoundaryCallback;
this.repository = repository;
this.contributionsRepository = contributionsRepository;
this.uploadRepository = uploadRepository;
this.ioThreadScheduler = ioThreadScheduler;
this.contributionsRemoteDataSource = contributionsRemoteDataSource;
compositeDisposable = new CompositeDisposable();
@ -68,7 +74,7 @@ public class PendingUploadsPresenter implements UserActionListener {
.setPageSize(10).build();
Factory<Integer, Contribution> factory;
factory = repository.fetchContributionsWithStatesSortedByDateUploadStarted(
factory = contributionsRepository.fetchContributionsWithStatesSortedByDateUploadStarted(
Arrays.asList(Contribution.STATE_QUEUED, Contribution.STATE_IN_PROGRESS,
Contribution.STATE_PAUSED));
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(factory,
@ -82,7 +88,7 @@ public class PendingUploadsPresenter implements UserActionListener {
.setPrefetchDistance(50)
.setPageSize(10).build();
Factory<Integer, Contribution> factory;
factory = repository.fetchContributionsWithStatesSortedByDateUploadStarted(
factory = contributionsRepository.fetchContributionsWithStatesSortedByDateUploadStarted(
Collections.singletonList(Contribution.STATE_FAILED));
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(factory,
pagedListConfig);
@ -103,7 +109,7 @@ public class PendingUploadsPresenter implements UserActionListener {
@Override
public void deleteUpload(final Contribution contribution, Context context) {
compositeDisposable.add(repository
compositeDisposable.add(contributionsRepository
.deleteContributionFromDB(contribution)
.subscribeOn(ioThreadScheduler)
.subscribe());
@ -111,14 +117,14 @@ public class PendingUploadsPresenter implements UserActionListener {
public void pauseUploads(List<Integer> states, int newState) {
CommonsApplication.isPaused = true ;
compositeDisposable.add(repository
compositeDisposable.add(contributionsRepository
.updateContributionWithStates(states, newState)
.subscribeOn(ioThreadScheduler)
.subscribe());
}
public void deleteUploads(List<Integer> states) {
compositeDisposable.add(repository
compositeDisposable.add(contributionsRepository
.deleteContributionsFromDBWithStates(states)
.subscribeOn(ioThreadScheduler)
.subscribe());
@ -132,27 +138,46 @@ public class PendingUploadsPresenter implements UserActionListener {
Contribution it = contributionList.get(index);
if (it.getState() == Contribution.STATE_FAILED) {
it.setDateUploadStarted(Calendar.getInstance().getTime());
if (it.getErrorInfo() == null){
if (it.getErrorInfo() == null) {
it.setChunkInfo(null);
it.setTransferred(0);
}
}
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(repository
.save(it)
.subscribeOn(ioThreadScheduler)
.doOnComplete(() -> {
restartUploads(contributionList, index + 1, context);
}
)
.subscribe(() ->
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
context, ExistingWorkPolicy.KEEP),
throwable -> {
compositeDisposable.add(uploadRepository
.checkDuplicateImage(it.getLocalUriPath().getPath())
.subscribeOn(ioThreadScheduler)
.subscribe(imageCheckResult -> {
if (imageCheckResult == IMAGE_OK) {
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(contributionsRepository
.save(it)
.subscribeOn(ioThreadScheduler)
.doOnComplete(() -> {
restartUploads(contributionList, index + 1, context);
})
.subscribe());
} else {
Timber.e("Contribution already exists");
compositeDisposable.add(contributionsRepository
.deleteContributionFromDB(it)
.subscribeOn(ioThreadScheduler).doOnComplete(() -> {
restartUploads(contributionList, index + 1, context);
})
.subscribe());
}
}, throwable -> {
Timber.e(throwable);
restartUploads(contributionList, index + 1, context);
}
));
}));
} else {
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(contributionsRepository
.save(it)
.subscribeOn(ioThreadScheduler)
.doOnComplete(() -> {
restartUploads(contributionList, index + 1, context);
})
.subscribe());
}
}
public void restartUpload(List<Contribution> contributionList, int index, Context context) {
@ -167,18 +192,31 @@ public class PendingUploadsPresenter implements UserActionListener {
it.setChunkInfo(null);
it.setTransferred(0);
}
compositeDisposable.add(uploadRepository
.checkDuplicateImage(it.getLocalUriPath().getPath())
.subscribeOn(ioThreadScheduler)
.subscribe(imageCheckResult -> {
if (imageCheckResult == IMAGE_OK) {
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(contributionsRepository
.save(it)
.subscribeOn(ioThreadScheduler)
.subscribe());
}else {
Timber.e("Contribution already exists");
compositeDisposable.add(contributionsRepository
.deleteContributionFromDB(it)
.subscribeOn(ioThreadScheduler)
.subscribe());
}
}));
} else {
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(contributionsRepository
.save(it)
.subscribeOn(ioThreadScheduler)
.subscribe());
}
it.setState(Contribution.STATE_QUEUED);
compositeDisposable.add(repository
.save(it)
.subscribeOn(ioThreadScheduler)
.subscribe(() ->
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
context, ExistingWorkPolicy.KEEP),
throwable -> {
Timber.e(throwable);
}
));
}
}

View file

@ -103,6 +103,16 @@ public class UploadModel {
return imageProcessingService.validateImage(uploadItem, inAppPictureLocation);
}
/**
* Calls checkDuplicateImage() of ImageProcessingService to check if image is duplicate
*
* @param filePath file to be checked
* @return IMAGE_DUPLICATE or IMAGE_OK
*/
public Single<Integer> checkDuplicateImage(String filePath){
return imageProcessingService.checkDuplicateImage(filePath);
}
/**
* Calls validateCaption() of ImageProcessingService to check caption of image
*