diff --git a/chrome/content/zotero/xpcom/sync/syncEngine.js b/chrome/content/zotero/xpcom/sync/syncEngine.js index 6f6042c04c..bbe772568d 100644 --- a/chrome/content/zotero/xpcom/sync/syncEngine.js +++ b/chrome/content/zotero/xpcom/sync/syncEngine.js @@ -228,15 +228,27 @@ Zotero.Sync.Data.Engine.prototype._startDownload = Zotero.Promise.coroutine(func // Get synced settings first, since they affect how other data is displayed let results = yield this._downloadSettings(libraryVersion); if (results.result == this.DOWNLOAD_RESULT_LIBRARY_UNMODIFIED) { - break; + let stop = true; + // If it's the first sync of the session or a manual sync and there are objects in the + // sync queue, or it's a subsequent auto-sync but there are objects that it's time to try + // again, go through all the steps even though the library version is unchanged. + // + // TODO: Skip the steps without queued objects. + if (this.firstInSession || !this.background) { + stop = !(yield Zotero.Sync.Data.Local.hasObjectsInSyncQueue(this.libraryID)); + } + else { + stop = !(yield Zotero.Sync.Data.Local.hasObjectsToTryInSyncQueue(this.libraryID)); + } + if (stop) { + break; + } } else if (results.result == this.DOWNLOAD_RESULT_RESTART) { yield this._onLibraryVersionChange(); continue loop; } - else { - newLibraryVersion = results.libraryVersion; - } + newLibraryVersion = results.libraryVersion; // // Get other object types @@ -319,7 +331,8 @@ Zotero.Sync.Data.Engine.prototype._downloadSettings = Zotero.Promise.coroutine(f Zotero.debug("Library " + this.libraryID + " hasn't been modified " + "-- skipping further object downloads"); return { - result: this.DOWNLOAD_RESULT_LIBRARY_UNMODIFIED + result: this.DOWNLOAD_RESULT_LIBRARY_UNMODIFIED, + libraryVersion: since }; } if (newLibraryVersion !== undefined && newLibraryVersion != results.libraryVersion) { @@ -406,9 +419,20 @@ Zotero.Sync.Data.Engine.prototype._downloadUpdatedObjects = Zotero.Promise.corou // (We don't know if the queued items are top-level or not, so we do them with child items.) let queuedKeys = []; if (objectType != 'item' || !options.top) { - queuedKeys = yield Zotero.Sync.Data.Local.getObjectsToTryFromSyncQueue( - objectType, this.libraryID - ); + if (this.firstInSession || !this.background) { + queuedKeys = yield Zotero.Sync.Data.Local.getObjectsFromSyncQueue( + objectType, this.libraryID + ); + } + else { + queuedKeys = yield Zotero.Sync.Data.Local.getObjectsToTryFromSyncQueue( + objectType, this.libraryID + ); + } + // Don't include items that just failed in the top-level run + if (this.failedItems.length) { + queuedKeys = Zotero.Utilities.arrayDiff(queuedKeys, this.failedItems); + } if (queuedKeys.length) { Zotero.debug(`Refetching ${queuedKeys.length} queued ` + (queuedKeys.length == 1 ? objectType : objectTypePlural)) diff --git a/chrome/content/zotero/xpcom/sync/syncLocal.js b/chrome/content/zotero/xpcom/sync/syncLocal.js index 91d52e4add..414a497f2c 100644 --- a/chrome/content/zotero/xpcom/sync/syncLocal.js +++ b/chrome/content/zotero/xpcom/sync/syncLocal.js @@ -1712,6 +1712,13 @@ Zotero.Sync.Data.Local = { }), + hasObjectsInSyncQueue: function (libraryID) { + return Zotero.DB.valueQueryAsync( + "SELECT ROWID FROM syncQueue WHERE libraryID=? LIMIT 1", libraryID + ).then(x => !!x); + }, + + getObjectsFromSyncQueue: function (objectType, libraryID) { return Zotero.DB.columnQueryAsync( "SELECT key FROM syncQueue WHERE libraryID=? AND " @@ -1721,6 +1728,25 @@ Zotero.Sync.Data.Local = { }, + hasObjectsToTryInSyncQueue: Zotero.Promise.coroutine(function* (libraryID) { + var rows = yield Zotero.DB.queryAsync( + "SELECT key, lastCheck, tries FROM syncQueue WHERE libraryID=?", libraryID + ); + for (let row of rows) { + let interval = this._syncQueueIntervals[row.tries]; + // Keep using last interval if beyond + if (!interval) { + interval = this._syncQueueIntervals[this._syncQueueIntervals.length - 1]; + } + let nextCheck = row.lastCheck + interval * 60 * 60; + if (nextCheck <= Zotero.Date.getUnixTimestamp()) { + return true; + } + } + return false; + }), + + getObjectsToTryFromSyncQueue: Zotero.Promise.coroutine(function* (objectType, libraryID) { var syncObjectTypeID = Zotero.Sync.Data.Utilities.getSyncObjectTypeID(objectType); var rows = yield Zotero.DB.queryAsync(