Create and use a common FolderOperation account operation class.
This commit is contained in:
parent
8827bc2a09
commit
9e93062d6f
3 changed files with 120 additions and 39 deletions
|
|
@ -15,12 +15,27 @@
|
|||
*
|
||||
* Execution of the operation is managed by {@link
|
||||
* AccountProcessor}. Since the processor will not en-queue duplicate
|
||||
* operations, implementations may override the {@link equal_to}
|
||||
* method to ensure that the same operation is not queued twice.
|
||||
* operations, implementations of this class may override the {@link
|
||||
* equal_to} method to specify which instances are considered to be
|
||||
* duplicates.
|
||||
*/
|
||||
public abstract class Geary.ImapEngine.AccountOperation : Geary.BaseObject {
|
||||
|
||||
|
||||
/** The account this operation applies to. */
|
||||
protected weak Geary.Account account;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new account operation.
|
||||
*
|
||||
* The passed in `account` will be the account the operation will
|
||||
* apply to.
|
||||
*/
|
||||
protected AccountOperation(Geary.Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired by after processing when the operation has completed.
|
||||
*
|
||||
|
|
@ -84,3 +99,57 @@ public abstract class Geary.ImapEngine.AccountOperation : Geary.BaseObject {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An account operation that applies to a specific folder.
|
||||
*
|
||||
* By default, instances of this class require that another operation
|
||||
* applies to the same folder as well as having the same type to be
|
||||
* considered equal, for the purpose of not en-queuing duplicate
|
||||
* operations.
|
||||
*/
|
||||
public abstract class Geary.ImapEngine.FolderOperation : AccountOperation {
|
||||
|
||||
|
||||
/** The folder this operation applies to. */
|
||||
protected weak Geary.Folder folder;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new folder operation.
|
||||
*
|
||||
* The passed in `folder` and `account` will be the objects the
|
||||
* operation will apply to.
|
||||
*/
|
||||
protected FolderOperation(Geary.Account account, Geary.Folder folder) {
|
||||
base(account);
|
||||
this.folder = folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if another operation is equal to this.
|
||||
*
|
||||
* This method compares both chain's up to {@link
|
||||
* AccountOperation.equal_to} and if equal, compares the paths of
|
||||
* both operation's folders to determine if `op` is equal to this
|
||||
* operation.
|
||||
*/
|
||||
public override bool equal_to(AccountOperation op) {
|
||||
return (
|
||||
base.equal_to(op) &&
|
||||
this.folder.path.equal_to(((FolderOperation) op).folder.path)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a representation of this operation for debugging.
|
||||
*
|
||||
* The return value will include its folder's path and the name of
|
||||
* the class.
|
||||
*/
|
||||
public override string to_string() {
|
||||
return "%s(%s)".printf(base.to_string(), folder.path.to_string());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -811,7 +811,6 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
|
|||
internal class Geary.ImapEngine.LoadFolders : AccountOperation {
|
||||
|
||||
|
||||
private weak GenericAccount account;
|
||||
private weak ImapDB.Account local;
|
||||
private Geary.SpecialFolderType[] specials;
|
||||
|
||||
|
|
@ -819,16 +818,17 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
|
|||
internal LoadFolders(GenericAccount account,
|
||||
ImapDB.Account local,
|
||||
Geary.SpecialFolderType[] specials) {
|
||||
this.account = account;
|
||||
base(account);
|
||||
this.local = local;
|
||||
this.specials = specials;
|
||||
}
|
||||
|
||||
public override async void execute(Cancellable cancellable) throws Error {
|
||||
GenericAccount generic = (GenericAccount) this.account;
|
||||
Gee.List<ImapDB.Folder> folders = new Gee.LinkedList<ImapDB.Folder>();
|
||||
yield enumerate_local_folders_async(folders, null, cancellable);
|
||||
debug("%s: found %u folders", to_string(), folders.size);
|
||||
this.account.add_folders(folders, true);
|
||||
generic.add_folders(folders, true);
|
||||
|
||||
if (!folders.is_empty) {
|
||||
// If we have some folders to load, then this isn't the
|
||||
|
|
@ -836,9 +836,12 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
|
|||
// exist
|
||||
foreach (Geary.SpecialFolderType special in this.specials) {
|
||||
try {
|
||||
yield this.account.ensure_special_folder_async(special, cancellable);
|
||||
yield generic.ensure_special_folder_async(special, cancellable);
|
||||
} catch (Error e) {
|
||||
warning("Unable to ensure special folder %s: %s", special.to_string(), e.message);
|
||||
warning(
|
||||
"Unable to ensure special folder %s: %s",
|
||||
special.to_string(), e.message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -876,7 +879,7 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
|
|||
internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
|
||||
|
||||
|
||||
private weak GenericAccount account;
|
||||
private weak GenericAccount generic_account;
|
||||
private weak Imap.Account remote;
|
||||
private weak ImapDB.Account local;
|
||||
private Gee.Collection<FolderPath> local_folders;
|
||||
|
|
@ -888,7 +891,8 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
|
|||
ImapDB.Account local,
|
||||
Gee.Collection<FolderPath> local_folders,
|
||||
Geary.SpecialFolderType[] specials) {
|
||||
this.account = account;
|
||||
base(account);
|
||||
this.generic_account = account;
|
||||
this.remote = remote;
|
||||
this.local = local;
|
||||
this.local_folders = local_folders;
|
||||
|
|
@ -1012,12 +1016,13 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
|
|||
debug("Unable to fetch local folder after cloning: %s", convert_err.message);
|
||||
}
|
||||
}
|
||||
this.account.add_folders(to_build, false);
|
||||
this.generic_account.add_folders(to_build, false);
|
||||
|
||||
if (remote_folders_suspect) {
|
||||
debug("Skipping removing folders due to prior errors");
|
||||
} else {
|
||||
Gee.List<MinimalFolder> removed = this.account.remove_folders(to_remove);
|
||||
Gee.List<MinimalFolder> removed =
|
||||
this.generic_account.remove_folders(to_remove);
|
||||
|
||||
// Sort by path length descending, so we always remove children first.
|
||||
removed.sort((a, b) => b.path.get_path_length() - a.path.get_path_length());
|
||||
|
|
@ -1046,13 +1051,15 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
|
|||
else
|
||||
debug("Unable to report %s altered: no local representation", altered_path.to_string());
|
||||
}
|
||||
this.account.update_folders(altered);
|
||||
this.generic_account.update_folders(altered);
|
||||
}
|
||||
|
||||
// Ensure each of the important special folders we need already exist
|
||||
foreach (Geary.SpecialFolderType special in this.specials) {
|
||||
try {
|
||||
yield this.account.ensure_special_folder_async(special, cancellable);
|
||||
yield this.generic_account.ensure_special_folder_async(
|
||||
special, cancellable
|
||||
);
|
||||
} catch (Error e) {
|
||||
warning("Unable to ensure special folder %s: %s", special.to_string(), e.message);
|
||||
}
|
||||
|
|
@ -1067,11 +1074,9 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
|
|||
* This performs a IMAP STATUS on the folder, but only if it is not
|
||||
* open - if it is open it is already maintaining its unseen count.
|
||||
*/
|
||||
internal class Geary.ImapEngine.RefreshFolderUnseen : AccountOperation {
|
||||
internal class Geary.ImapEngine.RefreshFolderUnseen : FolderOperation {
|
||||
|
||||
|
||||
private weak MinimalFolder folder;
|
||||
private weak GenericAccount account;
|
||||
private weak Imap.Account remote;
|
||||
private weak ImapDB.Account local;
|
||||
|
||||
|
|
@ -1080,23 +1085,11 @@ internal class Geary.ImapEngine.RefreshFolderUnseen : AccountOperation {
|
|||
GenericAccount account,
|
||||
Imap.Account remote,
|
||||
ImapDB.Account local) {
|
||||
this.folder = folder;
|
||||
this.account = account;
|
||||
base(account, folder);
|
||||
this.remote = remote;
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
public override bool equal_to(AccountOperation op) {
|
||||
return (
|
||||
base.equal_to(op) &&
|
||||
this.folder.path.equal_to(((RefreshFolderUnseen) op).folder.path)
|
||||
);
|
||||
}
|
||||
|
||||
public override string to_string() {
|
||||
return "%s(%s)".printf(base.to_string(), folder.path.to_string());
|
||||
}
|
||||
|
||||
public override async void execute(Cancellable cancellable) throws Error {
|
||||
if (this.folder.get_open_state() == Geary.Folder.OpenState.CLOSED) {
|
||||
Imap.Folder remote_folder = yield remote.fetch_folder_cached_async(
|
||||
|
|
@ -1106,13 +1099,13 @@ internal class Geary.ImapEngine.RefreshFolderUnseen : AccountOperation {
|
|||
);
|
||||
|
||||
if (remote_folder.properties.have_contents_changed(
|
||||
this.folder.local_folder.get_properties(),
|
||||
((MinimalFolder) this.folder).local_folder.get_properties(),
|
||||
this.folder.to_string())) {
|
||||
yield local.update_folder_status_async(
|
||||
remote_folder, false, true, cancellable
|
||||
);
|
||||
|
||||
this.account.update_folder(this.folder);
|
||||
((GenericAccount) this.account).update_folder(this.folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ public class Geary.ImapEngine.AccountProcessorTest : Gee.TestCase {
|
|||
|
||||
private Nonblocking.Spinlock spinlock = new Nonblocking.Spinlock();
|
||||
|
||||
internal TestOperation(Geary.Account account) {
|
||||
base(account);
|
||||
}
|
||||
|
||||
public override async void execute(Cancellable cancellable)
|
||||
throws Error {
|
||||
print("Test op/");
|
||||
|
|
@ -37,10 +41,16 @@ public class Geary.ImapEngine.AccountProcessorTest : Gee.TestCase {
|
|||
|
||||
public class OtherOperation : TestOperation {
|
||||
|
||||
internal OtherOperation(Geary.Account account) {
|
||||
base(account);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private AccountProcessor processor;
|
||||
private AccountProcessor? processor = null;
|
||||
private Geary.Account? account = null;
|
||||
private Geary.AccountInformation? info = null;
|
||||
private uint succeeded;
|
||||
private uint failed;
|
||||
private uint completed;
|
||||
|
|
@ -53,17 +63,26 @@ public class Geary.ImapEngine.AccountProcessorTest : Gee.TestCase {
|
|||
add_test("test_duplicate", test_duplicate);
|
||||
add_test("test_stop", test_stop);
|
||||
|
||||
// XXX this has to be here instead of in set_up for some
|
||||
// reason...
|
||||
this.processor = new AccountProcessor("processor");
|
||||
}
|
||||
|
||||
public override void set_up() {
|
||||
this.info = new Geary.AccountInformation(
|
||||
"test-info",
|
||||
File.new_for_path("."),
|
||||
File.new_for_path(".")
|
||||
);
|
||||
this.account = new Geary.MockAccount("test-account", this.info);
|
||||
|
||||
this.succeeded = 0;
|
||||
this.failed = 0;
|
||||
this.completed = 0;
|
||||
}
|
||||
|
||||
public void test_success() {
|
||||
TestOperation op = setup_operation(new TestOperation());
|
||||
TestOperation op = setup_operation(new TestOperation(this.account));
|
||||
|
||||
this.processor.enqueue(op);
|
||||
assert(this.processor.waiting == 1);
|
||||
|
|
@ -77,7 +96,7 @@ public class Geary.ImapEngine.AccountProcessorTest : Gee.TestCase {
|
|||
}
|
||||
|
||||
public void test_failure() {
|
||||
TestOperation op = setup_operation(new TestOperation());
|
||||
TestOperation op = setup_operation(new TestOperation(this.account));
|
||||
op.throw_error = true;
|
||||
|
||||
AccountOperation? error_op = null;
|
||||
|
|
@ -98,9 +117,9 @@ public class Geary.ImapEngine.AccountProcessorTest : Gee.TestCase {
|
|||
}
|
||||
|
||||
public void test_duplicate() {
|
||||
TestOperation op1 = setup_operation(new TestOperation());
|
||||
TestOperation op2 = setup_operation(new TestOperation());
|
||||
TestOperation op3 = setup_operation(new OtherOperation());
|
||||
TestOperation op1 = setup_operation(new TestOperation(this.account));
|
||||
TestOperation op2 = setup_operation(new TestOperation(this.account));
|
||||
TestOperation op3 = setup_operation(new OtherOperation(this.account));
|
||||
|
||||
this.processor.enqueue(op1);
|
||||
this.processor.enqueue(op2);
|
||||
|
|
@ -111,9 +130,9 @@ public class Geary.ImapEngine.AccountProcessorTest : Gee.TestCase {
|
|||
}
|
||||
|
||||
public void test_stop() {
|
||||
TestOperation op1 = setup_operation(new TestOperation());
|
||||
TestOperation op1 = setup_operation(new TestOperation(this.account));
|
||||
op1.wait_for_cancel = true;
|
||||
TestOperation op2 = setup_operation(new OtherOperation());
|
||||
TestOperation op2 = setup_operation(new OtherOperation(this.account));
|
||||
|
||||
this.processor.enqueue(op1);
|
||||
this.processor.enqueue(op2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue