Move deletion of unsent attachments into task.

This commit is contained in:
akwizgran
2019-06-17 16:07:16 +01:00
parent 9abe32ab4b
commit f3bbc7179e
2 changed files with 72 additions and 62 deletions

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android.attachment;
import android.arch.lifecycle.LiveData; import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData; import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.net.Uri; import android.net.Uri;
@@ -19,10 +20,14 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.Objects.requireNonNull;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.IoUtils.tryToClose;
@@ -31,12 +36,14 @@ import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.api.messaging.MessagingConstants.IMAGE_MIME_TYPES; import static org.briarproject.briar.api.messaging.MessagingConstants.IMAGE_MIME_TYPES;
@ThreadSafe
@NotNullByDefault @NotNullByDefault
class AttachmentCreationTask { class AttachmentCreationTask {
private static Logger LOG = private static Logger LOG =
getLogger(AttachmentCreationTask.class.getName()); getLogger(AttachmentCreationTask.class.getName());
private final Executor ioExecutor;
private final MessagingManager messagingManager; private final MessagingManager messagingManager;
private final ContentResolver contentResolver; private final ContentResolver contentResolver;
private final AttachmentRetriever retriever; private final AttachmentRetriever retriever;
@@ -47,9 +54,11 @@ class AttachmentCreationTask {
private volatile boolean canceled = false; private volatile boolean canceled = false;
AttachmentCreationTask(MessagingManager messagingManager, AttachmentCreationTask(Executor ioExecutor,
ContentResolver contentResolver, AttachmentRetriever retriever, MessagingManager messagingManager, ContentResolver contentResolver,
GroupId groupId, Collection<Uri> uris, boolean needsSize) { AttachmentRetriever retriever, GroupId groupId,
Collection<Uri> uris, boolean needsSize) {
this.ioExecutor = ioExecutor;
this.messagingManager = messagingManager; this.messagingManager = messagingManager;
this.contentResolver = contentResolver; this.contentResolver = contentResolver;
this.retriever = retriever; this.retriever = retriever;
@@ -63,21 +72,42 @@ class AttachmentCreationTask {
return result; return result;
} }
/**
* Cancels the task, asynchronously waits for it to finish, and deletes any
* created attachments.
*/
void cancel() { void cancel() {
canceled = true; canceled = true;
// Observe the task until it finishes (which may already have happened)
result.observeForever(new Observer<AttachmentResult>() {
@Override
public void onChanged(@Nullable AttachmentResult attachmentResult) {
requireNonNull(attachmentResult);
if (attachmentResult.isFinished()) {
deleteUnsentAttachments(attachmentResult.getItemResults());
result.removeObserver(this);
}
}
});
} }
@IoExecutor /**
* Asynchronously creates and stores the attachments.
*/
void storeAttachments() { void storeAttachments() {
List<AttachmentItemResult> results = new ArrayList<>(); ioExecutor.execute(() -> {
for (Uri uri : uris) { if (LOG.isLoggable(INFO))
if (canceled) break; LOG.info("Storing " + uris.size() + " attachments");
results.add(processUri(uri)); List<AttachmentItemResult> results = new ArrayList<>();
for (Uri uri : uris) {
if (canceled) break;
results.add(processUri(uri));
result.postValue(new AttachmentResult(new ArrayList<>(results),
false, false));
}
result.postValue(new AttachmentResult(new ArrayList<>(results), result.postValue(new AttachmentResult(new ArrayList<>(results),
false, false)); true, !canceled));
} });
result.postValue(new AttachmentResult(new ArrayList<>(results), true,
!canceled));
} }
@IoExecutor @IoExecutor
@@ -134,4 +164,24 @@ class AttachmentCreationTask {
logException(LOG, WARNING, e1); logException(LOG, WARNING, e1);
} }
} }
private void deleteUnsentAttachments(
Collection<AttachmentItemResult> itemResults) {
List<AttachmentHeader> headers = new ArrayList<>(itemResults.size());
for (AttachmentItemResult itemResult : itemResults) {
AttachmentItem item = itemResult.getItem();
if (item != null) headers.add(item.getHeader());
}
if (LOG.isLoggable(INFO))
LOG.info("Deleting " + headers.size() + " unsent attachments");
ioExecutor.execute(() -> {
for (AttachmentHeader header : headers) {
try {
messagingManager.removeAttachment(header);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
});
}
} }

View File

@@ -1,14 +1,11 @@
package org.briarproject.briar.android.attachment; package org.briarproject.briar.android.attachment;
import android.app.Application; import android.app.Application;
import android.arch.lifecycle.LiveData; import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -19,19 +16,12 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Objects.requireNonNull;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
public class AttachmentCreator { public class AttachmentCreator {
private static Logger LOG = getLogger(AttachmentCreator.class.getName());
private final Application app; private final Application app;
@IoExecutor @IoExecutor
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -58,9 +48,9 @@ public class AttachmentCreator {
Collection<Uri> uris) { Collection<Uri> uris) {
if (task != null) throw new IllegalStateException(); if (task != null) throw new IllegalStateException();
boolean needsSize = uris.size() == 1; boolean needsSize = uris.size() == 1;
task = new AttachmentCreationTask(messagingManager, task = new AttachmentCreationTask(ioExecutor, messagingManager,
app.getContentResolver(), retriever, groupId, uris, needsSize); app.getContentResolver(), retriever, groupId, uris, needsSize);
ioExecutor.execute(() -> task.storeAttachments()); task.storeAttachments();
return task.getResult(); return task.getResult();
} }
@@ -79,7 +69,8 @@ public class AttachmentCreator {
/** /**
* Returns the headers of any attachments created by * Returns the headers of any attachments created by
* {@link #storeAttachments(GroupId, Collection)}. * {@link #storeAttachments(GroupId, Collection)}, unless
* {@link #onAttachmentsSent()} or {@link #cancel()} has been called.
*/ */
@UiThread @UiThread
public List<AttachmentHeader> getAttachmentHeadersForSending() { public List<AttachmentHeader> getAttachmentHeadersForSending() {
@@ -100,50 +91,19 @@ public class AttachmentCreator {
*/ */
@UiThread @UiThread
public void onAttachmentsSent() { public void onAttachmentsSent() {
task = null; task = null; // Prevent cancel() from cancelling the task
} }
/** /**
* Cancels the task started by * Cancels the task started by
* {@link #storeAttachments(GroupId, Collection)} and deletes any * {@link #storeAttachments(GroupId, Collection)}, if any, unless
* created attachments, unless {@link #onAttachmentsSent()} has * {@link #onAttachmentsSent()} has been called.
* been called.
*/ */
@UiThread @UiThread
public void cancel() { public void cancel() {
if (task == null) return; // Already sent or cancelled if (task != null) {
task.cancel(); task.cancel();
// Observe the task until it finishes (which may already have task = null;
// happened) and delete any created attachments
LiveData<AttachmentResult> taskResult = task.getResult();
taskResult.observeForever(new Observer<AttachmentResult>() {
@Override
public void onChanged(@Nullable AttachmentResult result) {
requireNonNull(result);
if (result.isFinished()) {
deleteUnsentAttachments(result.getItemResults());
taskResult.removeObserver(this);
}
}
});
task = null;
}
private void deleteUnsentAttachments(
Collection<AttachmentItemResult> itemResults) {
List<AttachmentHeader> headers = new ArrayList<>(itemResults.size());
for (AttachmentItemResult itemResult : itemResults) {
AttachmentItem item = itemResult.getItem();
if (item != null) headers.add(item.getHeader());
} }
ioExecutor.execute(() -> {
for (AttachmentHeader header : headers) {
try {
messagingManager.removeAttachment(header);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
});
} }
} }