Merge branch 'wip/empty-folder-errors' into 'mainline'

Errors on emptying folders

See merge request GNOME/geary!280
This commit is contained in:
Michael Gratton 2019-08-11 23:02:06 +00:00
commit 659a23f4e6
2 changed files with 63 additions and 17 deletions

View file

@ -1230,10 +1230,14 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
protected async void expunge_all_async(Cancellable? cancellable = null) throws Error {
check_open("expunge_all_async");
EmptyFolder empty_folder = new EmptyFolder(this, cancellable);
replay_queue.schedule(empty_folder);
EmptyFolder op = new EmptyFolder(this, cancellable);
this.replay_queue.schedule(op);
yield op.wait_for_ready_async(cancellable);
yield empty_folder.wait_for_ready_async(cancellable);
// Checkpoint the replay queue, so it and the folder remains
// open while processing first the flag updates then the
// expunge from the remote
yield this.replay_queue.checkpoint(cancellable);
}
private void check_open(string method) throws EngineError {

View file

@ -60,6 +60,32 @@ private class Geary.ImapEngine.ReplayQueue : Geary.BaseObject {
}
}
private class WaitOperation : ReplayOperation {
public WaitOperation() {
// LOCAL_AND_REMOTE to make sure this operation is flushed
// all the way down the pipe
base("Wait", LOCAL_AND_REMOTE, OnError.IGNORE_REMOTE);
}
public override async ReplayOperation.Status replay_local_async()
throws GLib.Error {
return Status.CONTINUE;
}
public override async void replay_remote_async(Imap.FolderSession remote)
throws GLib.Error {
// Noop
}
public override string describe_state() {
return "";
}
}
public int local_count { get {
return local_queue.size;
} }
@ -230,23 +256,39 @@ private class Geary.ImapEngine.ReplayQueue : Geary.BaseObject {
return true;
}
private bool on_notification_timeout() {
if (notification_queue.size == 0)
return false;
debug("%s: Scheduling %d held server notification operations", owner.to_string(),
notification_queue.size);
// no new operations in timeout span, add them all to the "real" queue
foreach (ReplayOperation notification_op in notification_queue) {
if (!schedule(notification_op)) {
debug("Unable to schedule notification operation %s on %s", notification_op.to_string(),
to_string());
}
/** Waits until all pending operations have been processed. */
public async void checkpoint(GLib.Cancellable? cancellable)
throws GLib.Error {
WaitOperation wait_op = new WaitOperation();
if (schedule(wait_op)) {
yield wait_op.wait_for_ready_async(cancellable);
} else {
debug("Unable to schedule checkpoint op on %s", to_string());
}
}
notification_queue.clear();
/** Queues for any pending server notifications to be processed. */
public void flush_notifications() {
if (this.notification_queue.size > 0) {
debug("%s: Scheduling %d held server notification operations",
this.owner.to_string(),
this.notification_queue.size);
// no new operations in timeout span, add them all to the
// "real" queue
foreach (ReplayOperation notification_op in this.notification_queue) {
if (!schedule(notification_op)) {
debug("Unable to schedule notification operation %s on %s",
notification_op.to_string(),
to_string());
}
}
this.notification_queue.clear();
}
}
private bool on_notification_timeout() {
flush_notifications();
return false;
}