Tolerate 404 responses due to missing folders.

This prevents our own mailbox's download worker from getting stuck trying to list a folder that has been removed. Instead, the worker will move on to the next folder.
This commit is contained in:
akwizgran
2022-07-27 15:26:23 +01:00
parent 37ff06d192
commit 5defd500ae
8 changed files with 87 additions and 44 deletions

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
import org.briarproject.bramble.mailbox.MailboxApi.MailboxFile;
import org.briarproject.bramble.mailbox.MailboxApi.TolerableFailureException;
import java.io.IOException;
import java.util.LinkedList;
@@ -13,6 +14,7 @@ import java.util.Queue;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.Collections.emptyList;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
@ThreadSafe
@@ -43,8 +45,13 @@ class ContactMailboxDownloadWorker extends MailboxDownloadWorker {
LOG.info("Listing inbox");
MailboxFolderId folderId =
requireNonNull(mailboxProperties.getInboxId());
List<MailboxFile> files =
mailboxApi.getFiles(mailboxProperties, folderId);
List<MailboxFile> files;
try {
files = mailboxApi.getFiles(mailboxProperties, folderId);
} catch (TolerableFailureException e) {
LOG.warning("Inbox folder does not exist");
files = emptyList();
}
if (files.isEmpty()) {
onDownloadCycleFinished();
} else {

View File

@@ -91,9 +91,13 @@ interface MailboxApi {
* Used by owner and contacts to list their files to retrieve.
* <p>
* Returns 200 OK with the list of files in JSON.
*
* @throws TolerableFailureException if response code is 404 (folder does
* not exist or client is not authorised to download from it)
*/
List<MailboxFile> getFiles(MailboxProperties properties,
MailboxFolderId folderId) throws IOException, ApiException;
MailboxFolderId folderId)
throws IOException, ApiException, TolerableFailureException;
/**
* Used by owner and contacts to retrieve a file.
@@ -102,17 +106,22 @@ interface MailboxApi {
* in the response body.
*
* @param file the empty file the response bytes will be written into.
* @throws TolerableFailureException if response code is 404 (folder does
* not exist, client is not authorised to download from folder, or file
* does not exist)
*/
void getFile(MailboxProperties properties, MailboxFolderId folderId,
MailboxFileId fileId, File file) throws IOException, ApiException;
MailboxFileId fileId, File file)
throws IOException, ApiException, TolerableFailureException;
/**
* Used by owner and contacts to delete files.
* <p>
* Returns 200 OK (no exception) if deletion was successful.
*
* @throws TolerableFailureException on 404 response,
* because file was most likely deleted already.
* @throws TolerableFailureException if response code is 404 (folder does
* not exist, client is not authorised to download from folder, or file
* does not exist)
*/
void deleteFile(MailboxProperties properties, MailboxFolderId folderId,
MailboxFileId fileId)

View File

@@ -216,9 +216,11 @@ class MailboxApiImpl implements MailboxApi {
@Override
public List<MailboxFile> getFiles(MailboxProperties properties,
MailboxFolderId folderId) throws IOException, ApiException {
MailboxFolderId folderId)
throws IOException, ApiException, TolerableFailureException {
String path = "/files/" + folderId;
Response response = sendGetRequest(properties, path);
if (response.code() == 404) throw new TolerableFailureException();
if (response.code() != 200) throw new ApiException();
ResponseBody body = response.body();
@@ -252,9 +254,11 @@ class MailboxApiImpl implements MailboxApi {
@Override
public void getFile(MailboxProperties properties, MailboxFolderId folderId,
MailboxFileId fileId, File file) throws IOException, ApiException {
MailboxFileId fileId, File file)
throws IOException, ApiException, TolerableFailureException {
String path = "/files/" + folderId + "/" + fileId;
Response response = sendGetRequest(properties, path);
if (response.code() == 404) throw new TolerableFailureException();
if (response.code() != 200) throw new ApiException();
ResponseBody body = response.body();

View File

@@ -19,9 +19,7 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
@@ -161,9 +159,17 @@ abstract class MailboxDownloadWorker implements MailboxWorker,
void downloadNextFile(Queue<FolderFile> queue) {
synchronized (lock) {
if (state == State.DESTROYED) return;
FolderFile file = queue.remove();
apiCall = mailboxApiCaller.retryWithBackoff(
new SimpleApiCall(() -> apiCallDownloadFile(file, queue)));
if (queue.isEmpty()) {
// Check for files again, as new files may have arrived while
// we were downloading
apiCall = mailboxApiCaller.retryWithBackoff(
createApiCallForDownloadCycle());
} else {
FolderFile file = queue.remove();
apiCall = mailboxApiCaller.retryWithBackoff(
new SimpleApiCall(() ->
apiCallDownloadFile(file, queue)));
}
}
}
@@ -182,6 +188,14 @@ abstract class MailboxDownloadWorker implements MailboxWorker,
LOG.warning("Failed to delete temporary file");
}
throw e;
} catch (TolerableFailureException e) {
// File not found - continue to the next file
LOG.warning("File does not exist");
if (!tempFile.delete()) {
LOG.warning("Failed to delete temporary file");
}
downloadNextFile(queue);
return;
}
mailboxFileManager.handleDownloadedFile(tempFile);
deleteFile(file, queue);
@@ -204,20 +218,10 @@ abstract class MailboxDownloadWorker implements MailboxWorker,
mailboxApi.deleteFile(mailboxProperties, file.folderId,
file.fileId);
} catch (TolerableFailureException e) {
// Catch this so we can continue to the next file
logException(LOG, INFO, e);
}
if (queue.isEmpty()) {
// Check for files again, as new files may have arrived while we
// were downloading
synchronized (lock) {
if (state == State.DESTROYED) return;
apiCall = mailboxApiCaller.retryWithBackoff(
createApiCallForDownloadCycle());
}
} else {
downloadNextFile(queue);
// File not found - continue to the next file
LOG.warning("File does not exist");
}
downloadNextFile(queue);
}
@Override

View File

@@ -303,7 +303,7 @@ class OwnMailboxContactListWorker
mailboxApi.deleteContact(mailboxProperties, c);
} catch (TolerableFailureException e) {
// Catch this so we can continue to the next update
logException(LOG, INFO, e);
LOG.warning("Contact does not exist");
}
updateContactList();
}

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
import org.briarproject.bramble.mailbox.MailboxApi.MailboxFile;
import org.briarproject.bramble.mailbox.MailboxApi.TolerableFailureException;
import java.io.IOException;
import java.util.ArrayList;
@@ -85,9 +86,15 @@ class OwnMailboxDownloadWorker extends MailboxDownloadWorker {
if (state == State.DESTROYED) return;
}
LOG.info("Listing folder");
List<MailboxFile> files =
mailboxApi.getFiles(mailboxProperties, folder);
if (!files.isEmpty()) available.put(folder, new LinkedList<>(files));
try {
List<MailboxFile> files =
mailboxApi.getFiles(mailboxProperties, folder);
if (!files.isEmpty()) {
available.put(folder, new LinkedList<>(files));
}
} catch (TolerableFailureException e) {
LOG.warning("Folder does not exist");
}
if (queue.isEmpty()) {
LOG.info("Finished listing folders");
if (available.isEmpty()) onDownloadCycleFinished();