engine: Cancel any remote folders update before marking a message
When marking a message, a race condition can happen: - A remote folders update is already running - We mark the message locally and replay it remotely - The previous remote update result restores invalid values locally
This commit is contained in:
parent
f45afac091
commit
1a7a3a987a
5 changed files with 43 additions and 0 deletions
|
|
@ -2002,6 +2002,8 @@ private class Application.MarkEmailCommand : TrivialCommand, EmailCommand {
|
|||
|
||||
public override async void execute(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
this.location.account.cancel_remote_update();
|
||||
|
||||
yield this.store.mark_email_async(
|
||||
this.email, this.to_add, this.to_remove, cancellable
|
||||
);
|
||||
|
|
|
|||
|
|
@ -309,6 +309,11 @@ public abstract class Geary.Account : BaseObject, Logging.Source {
|
|||
*/
|
||||
public abstract bool is_open();
|
||||
|
||||
/**
|
||||
* Cancel any running/pending remote update for this {@link Account}.
|
||||
*/
|
||||
public abstract void cancel_remote_update();
|
||||
|
||||
/**
|
||||
* Rebuild the local data stores for this {@link Account}.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -78,6 +78,26 @@ internal class Geary.ImapEngine.AccountProcessor :
|
|||
this.queue.revoke(op);
|
||||
}
|
||||
|
||||
// Revokes all operations with the given type; returns true if at least one
|
||||
// operation with the given type was found
|
||||
public bool dequeue_by_type(GLib.Type type) {
|
||||
bool found = false;
|
||||
if (this.current_op != null &&
|
||||
this.current_op.get_type() == type &&
|
||||
this.op_cancellable != null) {
|
||||
this.op_cancellable.cancel();
|
||||
this.op_cancellable = null;
|
||||
found = true;
|
||||
}
|
||||
this.queue.revoke_matching((op) => {
|
||||
if (op.get_type() == type) {
|
||||
found = true;
|
||||
}
|
||||
return op.get_type() == type;
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.is_running = false;
|
||||
if (this.op_cancellable != null) {
|
||||
|
|
|
|||
|
|
@ -229,6 +229,15 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
|
|||
return open;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public override void cancel_remote_update() {
|
||||
// Cancel and update again
|
||||
if (this.processor.dequeue_by_type(typeof(UpdateRemoteFolders))) {
|
||||
debug("Cancelled a remote update! Updating again...\n");
|
||||
update_remote_folders(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override async void rebuild_async(GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
if (this.open) {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,13 @@ public class Mock.Account : Geary.Account,
|
|||
}
|
||||
}
|
||||
|
||||
public override void cancel_remote_update() {
|
||||
try {
|
||||
void_call("cancel_remote_update", {});
|
||||
} catch (GLib.Error err) {
|
||||
}
|
||||
}
|
||||
|
||||
public override async void rebuild_async(GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
void_call("rebuild_async", { cancellable });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue