[local-sync] Fix imap box status check

Summary:
When syncing folders, we check if the folder needs syncing by checking if it has any new messages via the STATUS command (STATUS returns uidnext, highestmodseq among others, and is cheaper than SELECT)

However, we can't issue a STATUS on a box that is already selected. Previously, if the box was already selected, we would just return it, but this was incorrect because we wouldn't get the latest box values (e.g. uidnext), causing us to think that there were no updates available, and skip syncing folders that actually needed to be synced.

Now, if the box is already selected when getting the status, we have to re select it to refresh the latest values

Test Plan: manual

Reviewers: evan, khamidou, spang

Reviewed By: spang

Differential Revision: https://phab.nylas.com/D3697
This commit is contained in:
Juan Tejada 2017-01-15 16:42:42 -08:00
parent 450f6fde13
commit c22703bd6e
2 changed files with 10 additions and 9 deletions

View file

@ -192,14 +192,14 @@ class IMAPConnection extends EventEmitter {
/** /**
* @return {Promise} that resolves to instance of IMAPBox * @return {Promise} that resolves to instance of IMAPBox
*/ */
openBox(folderName, {readOnly = false} = {}) { openBox(folderName, {readOnly = false, forceOpen = false} = {}) {
if (!folderName) { if (!folderName) {
throw new Error('IMAPConnection::openBox - You must provide a folder name') throw new Error('IMAPConnection::openBox - You must provide a folder name')
} }
if (!this._imap) { if (!this._imap) {
throw new IMAPConnectionNotReadyError(`IMAPConnection::openBox`) throw new IMAPConnectionNotReadyError(`IMAPConnection::openBox`)
} }
if (folderName === this.getOpenBoxName()) { if (!forceOpen && folderName === this.getOpenBoxName()) {
return Promise.resolve(new IMAPBox(this, this._imap._box)); return Promise.resolve(new IMAPBox(this, this._imap._box));
} }
this._isOpeningBox = true this._isOpeningBox = true
@ -213,13 +213,14 @@ class IMAPConnection extends EventEmitter {
}) })
} }
getBoxStatus(folderName) { getLatestBoxStatus(folderName) {
if (!folderName) { if (!folderName) {
throw new Error('IMAPConnection::getBoxStatus - You must provide a folder name') throw new Error('IMAPConnection::getLatestBoxStatus - You must provide a folder name')
} }
const openBoxName = this.getOpenBoxName() if (folderName === this.getOpenBoxName()) {
if (openBoxName === folderName) { // If the box is already open, we need to re-issue a SELECT in order to
return this._imap._box // get the latest stats from the box (e.g. latest uidnext, etc)
return this.openBox(folderName, {forceOpen: true})
} }
return this.createConnectionPromise((resolve, reject) => { return this.createConnectionPromise((resolve, reject) => {
return this._imap.statusAsync(folderName) return this._imap.statusAsync(folderName)

View file

@ -283,7 +283,7 @@ class FetchMessagesInFolderIMAP extends SyncTask {
* `Interruptible` * `Interruptible`
*/ */
async * _openMailboxAndEnsureValidity() { async * _openMailboxAndEnsureValidity() {
const box = yield this._imap.openBox(this._folder.name); const box = yield this._imap.openBox(this._folder.name, {forceOpen: true});
if (box.persistentUIDs === false) { if (box.persistentUIDs === false) {
throw new Error("Mailbox does not support persistentUIDs."); throw new Error("Mailbox does not support persistentUIDs.");
@ -488,7 +488,7 @@ class FetchMessagesInFolderIMAP extends SyncTask {
return true return true
} }
const boxStatus = yield this._imap.getBoxStatus(this._folder.name) const boxStatus = yield this._imap.getLatestBoxStatus(this._folder.name)
const {syncState} = this._folder const {syncState} = this._folder
const hasNewMessages = boxStatus.uidnext > syncState.fetchedmax const hasNewMessages = boxStatus.uidnext > syncState.fetchedmax