[geary/wip/avoid-fetch] Avoid fetching email if prior operation pulled it down
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/avoid-fetch] Avoid fetching email if prior operation pulled it down
- Date: Fri, 23 Jan 2015 02:51:16 +0000 (UTC)
commit 385db24dbeb9ee78965cec5bce4f51b84918728a
Author: Jim Nelson <jim yorba org>
Date: Thu Jan 22 18:50:34 2015 -0800
Avoid fetching email if prior operation pulled it down
This looks good but needs more testing before committing to master.
.../imap-engine-abstract-list-email.vala | 61 ++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
---
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
b/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
index 758c29b..d06e623 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
@@ -5,6 +5,8 @@
*/
private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.SendReplayOperation {
+ private static int total_fetches_avoided = 0;
+
private class RemoteBatchOperation : Nonblocking.BatchOperation {
// IN
public MinimalFolder owner;
@@ -121,6 +123,20 @@ private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.Sen
if (unfulfilled.size == 0)
return ReplayOperation.Status.COMPLETED;
+ // since list and search commands ahead of this one in the queue may have fulfilled some of
+ // the emails thought to be unfulfilled when first checked locally, look for them now
+ int fetches_avoided = yield remove_fulfilled_uids_async();
+ if (fetches_avoided > 0) {
+ total_fetches_avoided += fetches_avoided;
+
+ debug("*** %s: %d previously-fulfilled fetches avoided in list operation, %d total ***",
+ owner.to_string(), fetches_avoided, total_fetches_avoided);
+
+ // if all fulfilled, emails were added to accumulator in remove call, so done
+ if (unfulfilled.size == 0)
+ return ReplayOperation.Status.COMPLETED;
+ }
+
// convert UID -> needed fields mapping to needed fields -> UIDs, as they can be grouped
// and submitted at same time
Gee.HashMultiMap<Geary.Email.Field, Imap.UID> reverse_unfulfilled = new Gee.HashMultiMap<
@@ -311,6 +327,51 @@ private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.Sen
return uids != null && uids.size > 0 ? uids : null;
}
+ private async int remove_fulfilled_uids_async() throws Error {
+ // if the update is forced, don't rely on cached database, have to go to the horse's mouth
+ if (flags.is_force_update())
+ return 0;
+
+ ImapDB.Folder.ListFlags list_flags = ImapDB.Folder.ListFlags.from_folder_flags(flags);
+
+ Gee.Set<ImapDB.EmailIdentifier>? unfulfilled_ids = yield owner.local_folder.get_ids_async(
+ unfulfilled.keys, list_flags, cancellable);
+ if (unfulfilled_ids == null || unfulfilled_ids.size == 0)
+ return 0;
+
+ Gee.Map<ImapDB.EmailIdentifier, Email.Field>? local_fields =
+ yield owner.local_folder.list_email_fields_by_id_async(unfulfilled_ids, list_flags,
+ cancellable);
+ if (local_fields == null || local_fields.size == 0)
+ return 0;
+
+ // For each identifier, if now fulfilled in the database, fetch it, add it to the accumulator,
+ // and remove it from the unfulfilled map -- one network operation saved
+ int fetch_avoided = 0;
+ foreach (ImapDB.EmailIdentifier id in local_fields.keys) {
+ if (!local_fields.get(id).fulfills(required_fields))
+ continue;
+
+ try {
+ Email email = yield owner.local_folder.fetch_email_async(id, required_fields, list_flags,
+ cancellable);
+ accumulator.add(email);
+ } catch (Error err) {
+ if (err is IOError.CANCELLED)
+ throw err;
+
+ // some problem locally, do the network round-trip
+ continue;
+ }
+
+ // got it, don't fetch from remote
+ unfulfilled.unset(id.uid);
+ fetch_avoided++;
+ }
+
+ return fetch_avoided;
+ }
+
public override async void backout_local_async() throws Error {
// R/O, no backout
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]