[geary] Improved error detection and retry during folder open



commit c26525e6cd53b6727e34d5ed742a057753b3c5d1
Author: Jim Nelson <jim yorba org>
Date:   Tue May 13 18:33:09 2014 -0700

    Improved error detection and retry during folder open

 src/engine/api/geary-folder.vala                   |    3 +-
 .../imap-engine/imap-engine-minimal-folder.vala    |   28 +++++++++++++------
 src/engine/imap/api/imap-folder.vala               |   23 ++++++++++++---
 3 files changed, 39 insertions(+), 15 deletions(-)
---
diff --git a/src/engine/api/geary-folder.vala b/src/engine/api/geary-folder.vala
index c43fce0..e67dcd6 100644
--- a/src/engine/api/geary-folder.vala
+++ b/src/engine/api/geary-folder.vala
@@ -17,7 +17,8 @@ public interface Geary.Folder : BaseObject {
     
     public enum OpenFailed {
         LOCAL_FAILED,
-        REMOTE_FAILED
+        REMOTE_FAILED,
+        CANCELLED
     }
     
     /**
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index 631ec6a..a71e122 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -546,6 +546,8 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
         // ... in essence, guard against reentrancy, which is possible
         opening_monitor.notify_start();
         
+        // following blocks of code are fairly tricky because if the remote open fails need to
+        // carefully back out and possibly retry
         Imap.Folder? opening_folder = null;
         try {
             debug("Fetching information for remote folder %s", to_string());
@@ -594,15 +596,21 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
             }
         } catch (Error open_err) {
             bool hard_failure;
+            bool is_cancellation = false;
             if (open_err is ImapError || open_err is EngineError) {
-                if (open_err is ImapError.NOT_CONNECTED || open_err is ImapError.TIMED_OUT
-                    || open_err is EngineError.SERVER_UNAVAILABLE) {
-                    hard_failure = true;
-                } else {
-                    hard_failure = false;
-                }
+                // "hard" error in the sense of network conditions make connection impossible
+                // at the moment, "soft" error in the sense that some logical error prevented
+                // connect (like bad credentials)
+                hard_failure = open_err is ImapError.NOT_CONNECTED
+                    || open_err is ImapError.TIMED_OUT
+                    || open_err is ImapError.SERVER_ERROR
+                    || open_err is EngineError.SERVER_UNAVAILABLE;
+            } else if (open_err is IOError.CANCELLED) {
+                // user cancelled open, treat like soft error
+                hard_failure = false;
+                is_cancellation = true;
             } else {
-                // probably IOError, a hard failure
+                // a different IOError, a hard failure
                 hard_failure = true;
             }
             
@@ -619,7 +627,9 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
                 // soft failure, treat as failure to open
                 debug("Soft failure opening or preparing remote folder %s: %s", to_string(),
                     open_err.message);
-                notify_open_failed(Geary.Folder.OpenFailed.REMOTE_FAILED, open_err);
+                notify_open_failed(
+                    is_cancellation ? Folder.OpenFailed.CANCELLED : Folder.OpenFailed.REMOTE_FAILED,
+                    open_err);
                 
                 remote_reason = CloseReason.REMOTE_CLOSE;
                 force_reestablishment = false;
@@ -638,7 +648,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
             
             // schedule immediate close and force reestablishment
             close_internal_async.begin(CloseReason.LOCAL_CLOSE, remote_reason, force_reestablishment,
-                cancellable);
+                null);
             
             return;
         }
diff --git a/src/engine/imap/api/imap-folder.vala b/src/engine/imap/api/imap-folder.vala
index da6005e..c3fe6d4 100644
--- a/src/engine/imap/api/imap-folder.vala
+++ b/src/engine/imap/api/imap-folder.vala
@@ -108,12 +108,25 @@ private class Geary.Imap.Folder : BaseObject {
         
         properties.set_from_session_capabilities(session.capabilities);
         
-        StatusResponse response = yield session.select_async(
-            new MailboxSpecifier.from_folder_path(path, info.delim), cancellable);
-        if (response.status != Status.OK) {
-            yield release_session_async(cancellable);
+        StatusResponse? response = null;
+        Error? select_err = null;
+        try {
+            response = yield session.select_async(
+                new MailboxSpecifier.from_folder_path(path, info.delim), cancellable);
+        } catch (Error err) {
+            select_err = err;
+        }
+        
+        // if select_err is null, then response can not be null
+        if (select_err != null || response.status != Status.OK) {
+            // don't use user-supplied cancellable; it may be cancelled, and even if not, do not want
+            // to cancel this operation
+            yield release_session_async(null);
             
-            throw new ImapError.SERVER_ERROR("Unable to SELECT %s: %s", path.to_string(), 
response.to_string());
+            if (select_err != null)
+                throw select_err;
+            else
+                throw new ImapError.SERVER_ERROR("Unable to SELECT %s: %s", path.to_string(), 
response.to_string());
         }
         
         // if at end of SELECT command accepts_user_flags is still UNKKNOWN, treat as TRUE because,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]