From 651a199cb6782077b18cca1b35062404b1ef2486 Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Thu, 26 Jan 2017 16:03:53 -0800 Subject: [PATCH] [local-sync] Correctly check uidvalitity when syncing and save when updated Summary: If there were any uidvalidity changes after we've completely synced a folder, we would completely ignore them and not attempt to sync the folder. Also, we weren't saving the latest uidvalidity from the box to the folder syncState as soon as we recovered, we only saved it until after fetching messages. This meant that if the operation was interrupted before updating syncState.uidvalidity, we would always think that we were in a state of uid invalidity Recovering from uidvalidity was also broken because we weren't resetting the fetched ranges, and unnecessarily setting the folderId to null, which meant that we would never restore the uids of messages we had already fetched. Test Plan: manual Reviewers: evan, khamidou, mark, halla Reviewed By: mark Differential Revision: https://phab.nylas.com/D3796 --- .../fetch-messages-in-folder.imap.es6 | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/local-sync/src/local-sync-worker/sync-tasks/fetch-messages-in-folder.imap.es6 b/packages/local-sync/src/local-sync-worker/sync-tasks/fetch-messages-in-folder.imap.es6 index 5e1627d89..2f898e855 100644 --- a/packages/local-sync/src/local-sync-worker/sync-tasks/fetch-messages-in-folder.imap.es6 +++ b/packages/local-sync/src/local-sync-worker/sync-tasks/fetch-messages-in-folder.imap.es6 @@ -31,16 +31,23 @@ class FetchMessagesInFolderIMAP extends SyncTask { return this._folder.syncState.minUID == null; } - async _recoverFromUIDInvalidity() { + async _recoverFromUIDInvalidity(boxUidvalidity) { // UID invalidity means the server has asked us to delete all the UIDs for // this folder and start from scratch. Instead of deleting all the messages, - // we just remove the category ID and UID. We may re-assign the same message + // we just remove the folder ID and UID. We may re-assign the same message // the same UID. Otherwise they're eventually garbage collected. const {Message} = this._db; await Message.update({ - folderImapUID: null, folderId: null, + folderImapUID: null, }, {where: {folderId: this._folder.id}}) + + await this._folder.updateSyncState({ + fetchedmax: null, + fetchedmin: null, + minUID: null, + uidvalidity: boxUidvalidity, + }); } async _updateMessageAttributes(remoteUIDAttributes, localMessageAttributes) { @@ -308,11 +315,12 @@ class FetchMessagesInFolderIMAP extends SyncTask { throw new Error("Mailbox does not support persistentUIDs."); } + const boxUidvalidity = box.uidvalidity; const lastUIDValidity = this._folder.syncState.uidvalidity; - if (lastUIDValidity && (box.uidvalidity !== lastUIDValidity)) { + if (lastUIDValidity && (boxUidvalidity !== lastUIDValidity)) { console.log(`🔃 😵 📂 ${this._folder.name} - Recovering from UID invalidity`) - await this._recoverFromUIDInvalidity() + await this._recoverFromUIDInvalidity(boxUidvalidity) } return box; @@ -596,8 +604,8 @@ class FetchMessagesInFolderIMAP extends SyncTask { if (!this._folder.isSyncComplete()) { return true } - const {syncState} = this._folder - return boxStatus.uidnext > syncState.fetchedmax + const {syncState: {fetchedmax, uidvalidity}} = this._folder + return boxStatus.uidvalidity !== uidvalidity || boxStatus.uidnext > fetchedmax } _shouldFetchAttributes(boxStatus) {