Track and notify messages detached during cleanup

Split detach query into two so that messages identifiers can be captured
which are then used to signal through that the folder has locally
removed messages
This commit is contained in:
Chris Heywood 2020-01-08 11:31:25 +01:00
parent 52bd48bab5
commit cecf66df08
2 changed files with 46 additions and 8 deletions

View file

@ -882,16 +882,18 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
}, cancellable);
}
public async void detach_emails_before_timestamp(DateTime cutoff,
public async Gee.Collection<Geary.EmailIdentifier>? detach_emails_before_timestamp(DateTime cutoff,
Cancellable? cancellable) throws Error {
debug("Detaching emails before %s for folder ID %", cutoff.to_string(), this.folder_id.to_string());
Gee.Collection<Geary.EmailIdentifier>? deleted_ids = null;
yield db.exec_transaction_async(Db.TransactionType.WO, (cx) => {
// Query was found to be faster than other approaches. MessageLocationTable.ordering
// isn't relied on due to IMAP folder UIDs not guaranteed to be in order.
// MessageLocationTable.ordering isn't relied on due to IMAP folder
// UIDs not guaranteed to be in order.
StringBuilder sql = new StringBuilder();
sql.append("""
DELETE FROM MessageLocationTable
SELECT id, message_id, ordering
FROM MessageLocationTable
WHERE folder_id = ?
AND message_id IN (
SELECT id
@ -902,12 +904,45 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
""");
Db.Statement stmt = cx.prepare(sql.str);
stmt.bind_rowid(0, this.folder_id);
stmt.bind_rowid(0, folder_id);
stmt.bind_int64(1, cutoff.to_unix());
stmt.exec(cancellable);
return Db.TransactionOutcome.COMMIT;
Db.Result results = stmt.exec(cancellable);
StringBuilder? ids_sql_sublist = null;
while (!results.finished) {
if (ids_sql_sublist == null) {
deleted_ids = new Gee.ArrayList<Geary.EmailIdentifier>();
ids_sql_sublist = new StringBuilder();
} else {
ids_sql_sublist.append(",");
}
deleted_ids.add(new ImapDB.EmailIdentifier(results.int64_at(1), new Imap.UID(results.int64_at(2))));
ids_sql_sublist.append(results.rowid_at(0).to_string());
results.next(cancellable);
}
if (deleted_ids != null) {
sql = new StringBuilder();
sql.append("""
DELETE FROM MessageLocationTable
WHERE id IN (
""");
sql.append(ids_sql_sublist.str);
sql.append(")");
stmt = cx.prepare(sql.str);
stmt.exec(cancellable);
return Db.TransactionOutcome.COMMIT;
} else {
return Db.TransactionOutcome.DONE;
}
}, cancellable);
return deleted_ids;
}
public async void mark_email_async(Gee.Collection<ImapDB.EmailIdentifier> to_mark,

View file

@ -247,7 +247,10 @@ private class Geary.ImapEngine.CheckFolderSync : RefreshFolderSync {
// Detach older emails outside the prefetch window
if (this.account.information.prefetch_period_days >= 0) {
yield local_folder.detach_emails_before_timestamp(prefetch_max_epoch, cancellable);
Gee.Collection<Geary.EmailIdentifier>? detached_ids = yield local_folder.detach_emails_before_timestamp(prefetch_max_epoch, cancellable);
if (detached_ids != null) {
this.folder.email_locally_removed(detached_ids);
}
}
// get oldest local email and its time, as well as number