Make remote folder synchronisation a top-level API method
Add Geary.Folder::synchronise_remote method to allow clients to explicitly check for new mail in a folder. Move code from ImapEngine.AccountSynchronizer as the basic implementation, but also ensure pending replay queue notifications are processed before the process is complete.
This commit is contained in:
parent
ee11d0d8ec
commit
6871c1cd90
5 changed files with 53 additions and 27 deletions
|
|
@ -60,5 +60,10 @@ public abstract class Geary.AbstractLocalFolder : Geary.Folder {
|
|||
public override async void wait_for_close_async(Cancellable? cancellable = null) throws Error {
|
||||
yield closed_semaphore.wait_async(cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
public override async void synchronise_remote(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
// No-op
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -580,6 +580,19 @@ public abstract class Geary.Folder : BaseObject, Loggable {
|
|||
*/
|
||||
public abstract async void wait_for_close_async(Cancellable? cancellable = null) throws Error;
|
||||
|
||||
/**
|
||||
* Synchronises the local folder with the remote mailbox.
|
||||
*
|
||||
* If backed by a remote folder, this ensures that the end of the
|
||||
* vector is up to date with the end of the remote mailbox, and
|
||||
* that all messages in the vector satisfy the minimum
|
||||
* requirements for being used by the engine.
|
||||
*
|
||||
* The folder must be opened prior to attempting this operation.
|
||||
*/
|
||||
public abstract async void synchronise_remote(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error;
|
||||
|
||||
/**
|
||||
* List a number of contiguous emails in the folder's vector.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -114,12 +114,7 @@ private class Geary.ImapEngine.RefreshFolderSync : FolderOperation {
|
|||
bool was_opened = false;
|
||||
MinimalFolder minimal = (MinimalFolder) this.folder;
|
||||
try {
|
||||
// Open the folder on no delay since there's no point just
|
||||
// waiting around for it. Then claim a remote session so
|
||||
// we know that a remote connection has been made and the
|
||||
// folder has had a chance to normalise itself.
|
||||
yield minimal.open_async(Folder.OpenFlags.NO_DELAY, cancellable);
|
||||
yield minimal.claim_remote_session(cancellable);
|
||||
was_opened = true;
|
||||
debug("Synchronising %s", minimal.to_string());
|
||||
yield sync_folder(cancellable);
|
||||
|
|
@ -169,24 +164,9 @@ private class Geary.ImapEngine.RefreshFolderSync : FolderOperation {
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual async void sync_folder(Cancellable cancellable)
|
||||
throws Error {
|
||||
yield wait_for_prefetcher(cancellable);
|
||||
}
|
||||
|
||||
protected async void wait_for_prefetcher(Cancellable cancellable)
|
||||
throws Error {
|
||||
MinimalFolder minimal = (MinimalFolder) this.folder;
|
||||
try {
|
||||
yield minimal.email_prefetcher.active_sem.wait_async(cancellable);
|
||||
} catch (Error err) {
|
||||
Logging.debug(
|
||||
Logging.Flag.PERIODIC,
|
||||
"Error waiting for email prefetcher to complete %s: %s",
|
||||
folder.to_string(),
|
||||
err.message
|
||||
);
|
||||
}
|
||||
protected virtual async void sync_folder(GLib.Cancellable cancellable)
|
||||
throws GLib.Error {
|
||||
yield this.folder.synchronise_remote(cancellable);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -289,8 +269,9 @@ private class Geary.ImapEngine.CheckFolderSync : RefreshFolderSync {
|
|||
next_epoch = prefetch_max_epoch.add_days(-1);
|
||||
}
|
||||
|
||||
// let the prefetcher catch up
|
||||
yield wait_for_prefetcher(cancellable);
|
||||
// Wait for basic syncing (i.e. the prefetcher) to
|
||||
// complete as well.
|
||||
yield base.sync_folder(cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,12 +65,12 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
|
|||
internal ImapDB.Folder local_folder { get; private set; }
|
||||
|
||||
internal ReplayQueue? replay_queue { get; private set; default = null; }
|
||||
internal EmailPrefetcher email_prefetcher { get; private set; }
|
||||
internal ContactHarvester harvester { get; private set; }
|
||||
|
||||
private weak GenericAccount _account;
|
||||
private Geary.AggregatedFolderProperties _properties =
|
||||
new Geary.AggregatedFolderProperties(false, false);
|
||||
private EmailPrefetcher email_prefetcher;
|
||||
|
||||
private int open_count = 0;
|
||||
private Folder.OpenFlags open_flags = OpenFlags.NONE;
|
||||
|
|
@ -278,6 +278,28 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
|
|||
yield this.closed_semaphore.wait_async(cancellable);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public override async void synchronise_remote(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
check_open("synchronise_remote");
|
||||
// The normalisation process will pick up any missing messages
|
||||
// if closed so ensure there is a remote session
|
||||
Imap.FolderSession remote = yield claim_remote_session(cancellable);
|
||||
|
||||
// Send a NOOP so the server can return an untagged EXISTS if
|
||||
// any new messages have arrived since the remote was opened.
|
||||
yield remote.send_noop(cancellable);
|
||||
|
||||
// Wait until the replay queue has processed all notifications
|
||||
// so the prefetcher becomes aware of the new mail
|
||||
this.replay_queue.flush_notifications();
|
||||
yield this.replay_queue.checkpoint(cancellable);
|
||||
|
||||
// Finally, wait for the prefetcher to have finished
|
||||
// downloading the new mail.
|
||||
yield this.email_prefetcher.active_sem.wait_async(cancellable);
|
||||
}
|
||||
|
||||
// used by normalize_folders() during the normalization process; should not be used elsewhere
|
||||
private async void detach_all_emails_async(Cancellable? cancellable) throws Error {
|
||||
Gee.List<Email>? all = yield local_folder.list_email_by_id_async(null, -1,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ public class Geary.MockFolder : Folder, MockObject {
|
|||
throw new EngineError.UNSUPPORTED("Mock method");
|
||||
}
|
||||
|
||||
public override async void synchronise_remote(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
void_call("synchronise_remote", { cancellable });
|
||||
}
|
||||
|
||||
public override async Gee.List<Geary.Email>?
|
||||
list_email_by_id_async(Geary.EmailIdentifier? initial_id,
|
||||
int count,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue