[geary/wip/unread-status-714865: 6/10] Only update one folder at a time



commit b3130c7eaffb45e084923270c76d59a897675c0a
Author: Charles Lindsay <chaz yorba org>
Date:   Thu Feb 20 15:47:50 2014 -0800

    Only update one folder at a time

 .../imap-engine/imap-engine-generic-account.vala   |   54 +++++++++----------
 src/engine/imap/api/imap-account.vala              |   43 ++++-----------
 2 files changed, 38 insertions(+), 59 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 0b764c1..8ab2628 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -17,7 +17,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
     private Gee.HashMap<FolderPath, MinimalFolder> folder_map = new Gee.HashMap<
         FolderPath, MinimalFolder>();
     private Gee.HashMap<FolderPath, Folder> local_only = new Gee.HashMap<FolderPath, Folder>();
-    private uint refresh_unseen_timeout_id = 0;
+    private Gee.HashMap<FolderPath, uint> refresh_unseen_timeout_ids
+        = new Gee.HashMap<FolderPath, uint>();
     private uint refresh_folder_timeout_id = 0;
     private bool in_refresh_enumerate = false;
     private Cancellable refresh_cancellable = new Cancellable();
@@ -72,23 +73,23 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
     
     protected override void notify_email_appended(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> 
ids) {
         base.notify_email_appended(folder, ids);
-        reschedule_unseen_update();
+        reschedule_unseen_update(folder);
     }
     
     protected override void notify_email_inserted(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> 
ids) {
         base.notify_email_inserted(folder, ids);
-        reschedule_unseen_update();
+        reschedule_unseen_update(folder);
     }
     
     protected override void notify_email_removed(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> 
ids) {
         base.notify_email_removed(folder, ids);
-        reschedule_unseen_update();
+        reschedule_unseen_update(folder);
     }
     
     protected override void notify_email_flags_changed(Geary.Folder folder,
         Gee.Map<Geary.EmailIdentifier, Geary.EmailFlags> flag_map) {
         base.notify_email_flags_changed(folder, flag_map);
-        reschedule_unseen_update();
+        reschedule_unseen_update(folder);
     }
     
     private void check_open() throws EngineError {
@@ -284,22 +285,24 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         return all_folders;
     }
     
-    private void reschedule_unseen_update() {
-        if (refresh_unseen_timeout_id != 0) {
-            Source.remove(refresh_unseen_timeout_id);
-            refresh_unseen_timeout_id = 0;
-        }
+    private void reschedule_unseen_update(Geary.Folder folder) {
+        if (!folder_map.has_key(folder.path))
+            return;
         
-        refresh_unseen_timeout_id = Timeout.add_seconds(REFRESH_UNSEEN_SEC, on_refresh_unseen);
+        if (refresh_unseen_timeout_ids.get(folder.path) != 0)
+            Source.remove(refresh_unseen_timeout_ids.get(folder.path));
+        
+        refresh_unseen_timeout_ids.set(folder.path,
+            Timeout.add_seconds(REFRESH_UNSEEN_SEC, () => on_refresh_unseen(folder)));
     }
     
-    private bool on_refresh_unseen() {
+    private bool on_refresh_unseen(Geary.Folder folder) {
         // TODO: prevent recursion?
         
         // TODO: cancellable?
-        refresh_unseen_async.begin(null, on_refresh_unseen_completed);
+        refresh_unseen_async.begin(folder, null, on_refresh_unseen_completed);
         
-        refresh_unseen_timeout_id = 0;
+        refresh_unseen_timeout_ids.unset(folder.path);
         return false;
     }
     
@@ -311,20 +314,15 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         }
     }
     
-    private async void refresh_unseen_async(Cancellable? cancellable) throws Error {
-        debug("Refreshing unseen counts");
+    private async void refresh_unseen_async(Geary.Folder folder, Cancellable? cancellable) throws Error {
+        debug("Refreshing unseen counts for %s", folder.to_string());
         
-        Gee.Map<FolderPath, int> unseen_counts = yield remote.fetch_all_unseen_async(cancellable);
-        foreach (FolderPath path in unseen_counts.keys) {
-            if (!folder_map.has_key(path)) {
-                debug("Unknown folder path %s returned from unseen counts", path.to_string());
-                continue;
-            }
-            
-            MinimalFolder folder = folder_map.get(path);
-            folder.remote_folder.properties.set_status_unseen(unseen_counts.get(path));
-            yield local.update_folder_status_async(folder.remote_folder, false, cancellable);
-        }
+        int unseen_count = yield remote.fetch_unseen_count_async(folder.path, cancellable);
+        
+        Imap.Folder remote_folder = yield remote.fetch_folder_async(folder.path, cancellable);
+        // TODO: nothing to refresh if that fetch just hit the network.
+        remote_folder.properties.set_status_unseen(unseen_count);
+        yield local.update_folder_status_async(remote_folder, false, cancellable);
     }
     
     private void reschedule_folder_refresh(bool immediate) {
diff --git a/src/engine/imap/api/imap-account.vala b/src/engine/imap/api/imap-account.vala
index 72f905d..976a9ba 100644
--- a/src/engine/imap/api/imap-account.vala
+++ b/src/engine/imap/api/imap-account.vala
@@ -183,7 +183,7 @@ private class Geary.Imap.Account : BaseObject {
         
         Imap.Folder folder;
         if (!mailbox_info.attrs.is_no_select) {
-            StatusData status = yield fetch_status_async(path, cancellable);
+            StatusData status = yield fetch_status_async(path, StatusDataType.all(), cancellable);
             
             folder = new Imap.Folder(session_mgr, status, mailbox_info);
         } else {
@@ -195,13 +195,22 @@ private class Geary.Imap.Account : BaseObject {
         return folder;
     }
     
-    private async StatusData fetch_status_async(FolderPath path, Cancellable? cancellable)
+    public async int fetch_unseen_count_async(FolderPath path, Cancellable? cancellable)
         throws Error {
         check_open();
         
+        // TODO: check mailbox_info.attrs.is_no_select first?
+        StatusData data = yield fetch_status_async(path, { StatusDataType.UNSEEN }, cancellable);
+        return data.unseen;
+    }
+    
+    private async StatusData fetch_status_async(FolderPath path, StatusDataType[] status_types,
+        Cancellable? cancellable) throws Error {
+        check_open();
+        
         Gee.List<StatusData> status_results = new Gee.ArrayList<StatusData>();
         StatusResponse response = yield send_command_async(
-            new StatusCommand(new MailboxSpecifier.from_folder_path(path, null), StatusDataType.all()),
+            new StatusCommand(new MailboxSpecifier.from_folder_path(path, null), status_types),
             null, status_results, cancellable);
         
         throw_fetch_error(response, path, status_results.size);
@@ -224,34 +233,6 @@ private class Geary.Imap.Account : BaseObject {
         }
     }
     
-    public async Gee.Map<FolderPath, int> fetch_all_unseen_async(Cancellable? cancellable) throws Error {
-        Gee.HashMap<MailboxSpecifier, FolderPath> paths = new Gee.HashMap<MailboxSpecifier, FolderPath>();
-        foreach (FolderPath p in folders.keys) {
-            try {
-                paths.set(new MailboxSpecifier.from_folder_path(p, null), p);
-            } catch (Error e) {
-                debug("Error converting folder path %s to mailbox specifier: %s", p.to_string(), e.message);
-            }
-        }
-        
-        Gee.ArrayList<StatusCommand> commands = Geary.traverse<MailboxSpecifier>(paths.keys)
-            .map<StatusCommand>(m => new StatusCommand(m, { StatusDataType.UNSEEN }))
-            .to_array_list();
-        Gee.ArrayList<StatusData> status_results = new Gee.ArrayList<StatusData>();
-        Gee.Map<Command, StatusResponse> responses = yield send_multiple_async(commands,
-            null, status_results, cancellable);
-        
-        // TODO: check responses?
-        (void) responses;
-        
-        Gee.HashMap<FolderPath, int> unseen_counts = new Gee.HashMap<FolderPath, int>();
-        foreach (StatusData data in status_results) {
-            assert(paths.has_key(data.mailbox));
-            unseen_counts.set(paths.get(data.mailbox), data.unseen);
-        }
-        return unseen_counts;
-    }
-    
     public async Gee.List<Imap.Folder>? list_child_folders_async(FolderPath? parent, Cancellable? 
cancellable)
         throws Error {
         check_open();


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