[geary/wip/131-sent-mail: 18/18] Clean up ImapEngine.CreateEmail replay op source code



commit 60b6ad9770162801832e841c29de51e40c9ac144
Author: Michael Gratton <mike vee net>
Date:   Sat Aug 10 12:10:53 2019 +1000

    Clean up ImapEngine.CreateEmail replay op source code

 .../replay-ops/imap-engine-create-email.vala       | 92 +++++++++++++++-------
 1 file changed, 62 insertions(+), 30 deletions(-)
---
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-create-email.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-create-email.vala
index ca5e29c9..9d519c47 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-create-email.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-create-email.vala
@@ -1,10 +1,13 @@
-/* Copyright 2016 Software Freedom Conservancy Inc.
+/*
+ * Copyright 2016 Software Freedom Conservancy Inc.
+ * Copyright 2019 Michael Gratton <mike vee net>
  *
  * This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later).  See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
  */
 
-private class Geary.ImapEngine.CreateEmail : Geary.ImapEngine.SendReplayOperation {
+private class Geary.ImapEngine.CreateEmail : SendReplayOperation {
+
     public Geary.EmailIdentifier? created_id { get; private set; default = null; }
 
     private MinimalFolder engine;
@@ -13,8 +16,12 @@ private class Geary.ImapEngine.CreateEmail : Geary.ImapEngine.SendReplayOperatio
     private DateTime? date_received;
     private Cancellable? cancellable;
 
-    public CreateEmail(MinimalFolder engine, RFC822.Message rfc822, Geary.EmailFlags? flags,
-        DateTime? date_received, Cancellable? cancellable) {
+
+    public CreateEmail(MinimalFolder engine,
+                       RFC822.Message rfc822,
+                       EmailFlags? flags,
+                       DateTime? date_received,
+                       GLib.Cancellable? cancellable) {
         base.only_remote("CreateEmail", OnError.RETRY);
 
         this.engine = engine;
@@ -28,34 +35,35 @@ private class Geary.ImapEngine.CreateEmail : Geary.ImapEngine.SendReplayOperatio
     public override async void replay_remote_async(Imap.FolderSession remote)
         throws GLib.Error {
         // Deal with cancellable manually since create_email_async cannot be cancelled.
-        if (cancellable.is_cancelled())
+        if (this.cancellable.is_cancelled()) {
             throw new IOError.CANCELLED("CreateEmail op cancelled immediately");
+        }
 
-        // use IMAP APPEND command on remote folders, which doesn't require opening a folder ...
-        // if retrying after a successful create, rfc822 will be null
-        if (rfc822 != null)
-            created_id = yield remote.create_email_async(rfc822, flags, date_received);
+        // use IMAP APPEND command on remote folders, which doesn't
+        // require opening a folder ...  if retrying after a
+        // successful create, rfc822 will be null
+        if (this.rfc822 != null) {
+            this.created_id = yield remote.create_email_async(
+                this.rfc822, this.flags, this.date_received
+            );
+        }
 
-        // because this command retries, the create completed, remove the RFC822 message to prevent
-        // creating it twice
-        rfc822 = null;
+        // because this command retries, the create completed, remove
+        // the RFC822 message to prevent creating it twice
+        this.rfc822 = null;
 
-        // If the user cancelled the operation, we need to wipe the new message to keep this
-        // operation atomic.
-        if (cancellable.is_cancelled()) {
-            if (created_id != null) {
-                yield remote.remove_email_async(
-                    new Imap.MessageSet.uid(((ImapDB.EmailIdentifier) created_id).uid).to_list(),
-                    null
-                );
-            }
-
-            throw new IOError.CANCELLED("CreateEmail op cancelled after create");
-        }
+        // Bail out early if cancelled
+        yield check_cancelled(remote);
 
-        if (created_id != null) {
-            // TODO: need to prevent gaps that may occur here
-            Geary.Email created = new Geary.Email(created_id);
+        if (this.created_id != null) {
+            // Since the server provided the UID of the new message,
+            // it is possible to email locally then fill in the
+            // missing parts from the remote.
+            //
+            // TODO: need to prevent gaps between UIDS that may occur
+            // here if this is created before we know of an earlier
+            // message that has arrived.
+            Geary.Email created = new Geary.Email(this.created_id);
             Gee.Map<Geary.Email, bool> results =
                 yield this.engine.local_folder.create_or_merge_email_async(
                     Geary.iterate<Geary.Email>(created).to_array_list(),
@@ -63,10 +71,14 @@ private class Geary.ImapEngine.CreateEmail : Geary.ImapEngine.SendReplayOperatio
                     this.engine.harvester,
                     this.cancellable
                 );
+
             if (results.size > 0) {
-                created_id = Collection.get_first<Geary.Email>(results.keys).id;
+                this.created_id = Collection.get_first<Email>(results.keys).id;
             } else {
-                created_id = null;
+                // Something went wrong creating/merging the message,
+                // so pretend we don't know what its UID is so the
+                // background sync goes off and gets it.
+                this.created_id = null;
             }
         }
     }
@@ -77,4 +89,24 @@ private class Geary.ImapEngine.CreateEmail : Geary.ImapEngine.SendReplayOperatio
         );
     }
 
+    private async void check_cancelled(Imap.FolderSession remote)
+        throws GLib.Error {
+        if (this.cancellable.is_cancelled()) {
+            // Need to wipe the new message if possible to keep the
+            // operation atomic.
+            if (this.created_id != null) {
+                yield remote.remove_email_async(
+                    new Imap.MessageSet.uid(
+                        ((ImapDB.EmailIdentifier) this.created_id).uid
+                    ).to_list(),
+                    // Don't observe the cancellable since it's
+                    // already cancelled
+                    null
+                );
+            }
+
+            throw new IOError.CANCELLED("CreateEmail op cancelled after create");
+        }
+    }
+
 }


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