[geary/mjog/invert-folder-class-hierarchy: 335/362] Geary.ImapEngine.ReplayQueue: Only flush ops on close if still running




commit 0e19577e68920d2125039045fb5906e5a27edfce
Author: Michael Gratton <mike vee net>
Date:   Tue Feb 16 09:09:46 2021 +1100

    Geary.ImapEngine.ReplayQueue: Only flush ops on close if still running
    
    Flush ops when being closed only if the queue is currently running. It
    should only be running if online, but also if not running it will not
    be able to process any ops anyway.
    
    This prevents close hanging indefinitely when not online.

 .../imap-engine/imap-engine-minimal-folder.vala    |  5 +---
 .../imap-engine/imap-engine-replay-queue.vala      | 33 ++++++++++++++++------
 2 files changed, 25 insertions(+), 13 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index 5f4b1a0c0..34c1d606a 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -134,7 +134,6 @@ private class Geary.ImapEngine.MinimalFolder : BaseObject,
         this._used_as = use;
 
         this.replay_queue = new ReplayQueue(this);
-        this.replay_queue.remotely_executed.connect(this.on_remote_status_check);
 
         this.email_prefetcher = new EmailPrefetcher(this);
         update_harvester();
@@ -266,7 +265,7 @@ private class Geary.ImapEngine.MinimalFolder : BaseObject,
      * Shuts down the folder in preparation for account close.
      */
     internal async void close() throws GLib.Error {
-        yield this.replay_queue.close_async(true);
+        yield this.replay_queue.close();
         yield close_remote_session();
         yield this.closed_semaphore.wait_async(null);
     }
@@ -777,8 +776,6 @@ private class Geary.ImapEngine.MinimalFolder : BaseObject,
 
     /**
      * Closes the folder and the remote session.
-     *
-     * This should only be called from the replay queue.
      */
     private async void close_remote_session() {
         lock (this.remote_session) {
diff --git a/src/engine/imap-engine/imap-engine-replay-queue.vala 
b/src/engine/imap-engine/imap-engine-replay-queue.vala
index cfeea3ba2..5cea1f716 100644
--- a/src/engine/imap-engine/imap-engine-replay-queue.vala
+++ b/src/engine/imap-engine/imap-engine-replay-queue.vala
@@ -38,9 +38,14 @@ private class Geary.ImapEngine.ReplayQueue : BaseObject, Logging.Source {
         bool local_closed = false;
         bool remote_closed = false;
 
-        public CloseReplayQueue() {
-            // LOCAL_AND_REMOTE to make sure this operation is flushed all the way down the pipe
-            base ("CloseReplayQueue", ReplayOperation.Scope.LOCAL_AND_REMOTE, OnError.IGNORE_REMOTE);
+        public CloseReplayQueue(bool flush_remote) {
+            base(
+                "CloseReplayQueue",
+                flush_remote
+                    ? ReplayOperation.Scope.LOCAL_AND_REMOTE
+                    : ReplayOperation.Scope.LOCAL_ONLY,
+                IGNORE_REMOTE
+            );
         }
 
         public override async ReplayOperation.Status replay_local_async()
@@ -105,7 +110,15 @@ private class Geary.ImapEngine.ReplayQueue : BaseObject, Logging.Source {
 
     public bool has_remote_operation {
         get {
-            return this.remote_op_active != null || !this.remote_queue.is_empty;
+            return (
+                this.remote_op_active != null ||
+                !this.remote_queue.is_empty ||
+                (this.local_op_active != null &&
+                 this.local_op_active.scope == LOCAL_AND_REMOTE) ||
+                this.local_queue.get_all().any_match(
+                    op => (op.scope == LOCAL_AND_REMOTE)
+                )
+            );
         }
     }
 
@@ -392,10 +405,13 @@ private class Geary.ImapEngine.ReplayQueue : BaseObject, Logging.Source {
      *
      * A ReplayQueue cannot be re-opened.
      */
-    public async void close_async(bool flush_pending, Cancellable? cancellable = null) throws Error {
+    public async void close(GLib.Cancellable? cancellable = null)
+        throws GLib.Error {
         if (state != State.OPEN)
             return;
 
+        var flush_pending = !this.remote_cancellable.is_cancelled();
+
         // cancel notification queue timeout
         if (notification_timer != null)
             notification_timer.cancel();
@@ -418,9 +434,8 @@ private class Geary.ImapEngine.ReplayQueue : BaseObject, Logging.Source {
         }
 
         // flush a ReplayClose operation down the pipe so all working operations complete
-        CloseReplayQueue close_op = new CloseReplayQueue();
-        bool is_scheduled = schedule(close_op);
-        assert(is_scheduled);
+        CloseReplayQueue close_op = new CloseReplayQueue(flush_pending);
+        schedule(close_op);
 
         yield close_op.wait_for_ready_async(cancellable);
 
@@ -611,7 +626,7 @@ private class Geary.ImapEngine.ReplayQueue : BaseObject, Logging.Source {
             remotely_executing(op);
 
             GLib.Error? remote_err = null;
-            if (remote != null) {
+            if (remote != null || is_close_op) {
                 if (op.remote_retry_count > 0)
                     debug("Retrying op %s on %s", op.to_string(), to_string());
 


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