Reduce auto-sync timeout to 3 seconds and optimize auto-sync process

Reduce timeout after an object change from 15 seconds to 3 seconds,
ecxept for individual notes. We should probably kick off an auto-sync
3 seconds after a note is blurred, but that's not implemented.

We also now skip file syncing and full-text content syncing altogether
unless an attachment has changed.

Reindexing an item now kicks off auto-sync, whereas before it didn't.
This commit is contained in:
Dan Stillman 2021-04-06 04:57:19 -04:00
parent 205fe7f032
commit 52932b6eb0
5 changed files with 90 additions and 15 deletions

View file

@ -290,6 +290,7 @@ Zotero.Fulltext = Zotero.FullText = new function(){
Zotero.DB.query(sql, [itemID, {string:text}]);
*/
Zotero.Notifier.queue('index', 'item', itemID);
Zotero.Notifier.queue('refresh', 'item', itemID);
}.bind(this));

View file

@ -93,7 +93,7 @@ Zotero.Notifier = new function(){
* Possible values:
*
* event: 'add', 'modify', 'delete', 'move' ('c', for changing parent),
* 'remove' (ci, it), 'refresh', 'redraw', 'trash', 'unreadCountUpdated'
* 'remove' (ci, it), 'refresh', 'redraw', 'trash', 'unreadCountUpdated', 'index'
* type - 'collection', 'search', 'item', 'collection-item', 'item-tag', 'tag',
* 'group', 'relation', 'feed', 'feedItem'
* ids - single id or array of ids

View file

@ -99,7 +99,8 @@ Zotero.Sync.EventListeners.ChangeListener = new function () {
Zotero.Sync.EventListeners.AutoSyncListener = {
_editTimeout: 15,
_editTimeout: 3,
_noteEditTimeout: 15,
_observerID: null,
init: function () {
@ -114,13 +115,15 @@ Zotero.Sync.EventListeners.AutoSyncListener = {
},
notify: function (event, type, ids, extraData) {
// TODO: skip others
if (event == 'refresh' || event == 'redraw') {
return;
}
if (Zotero.Sync.Runner.syncInProgress) {
return;
switch (event) {
case 'add':
case 'modify':
case 'delete':
case 'index':
break;
default:
return;
}
// Only trigger sync for certain types
@ -131,6 +134,8 @@ Zotero.Sync.EventListeners.AutoSyncListener = {
// Determine affected libraries so only those can be synced
let libraries = [];
var fileLibraries = new Set();
var fullTextLibraries = new Set();
if (type == 'setting') {
for (let id of ids) {
@ -163,11 +168,33 @@ Zotero.Sync.EventListeners.AutoSyncListener = {
return;
}
var noteEdit = false;
if (type == 'item' && (event == 'add' || event == 'modify' || event == 'index')) {
// Use a longer timeout for a single note edit, to avoid repeating syncing during typing
if (ids.length == 1 && (Zotero.Items.get(ids[0]) || {}).itemType == 'note') {
noteEdit = true;
}
else {
for (let id of ids) {
let item = Zotero.Items.get(id);
if (!item) continue;
if (item.isStoredFileAttachment()) {
fileLibraries.add(item.libraryID);
}
if (item.isFileAttachment()) {
fullTextLibraries.add(item.libraryID);
}
}
}
}
Zotero.Sync.Runner.setSyncTimeout(
this._editTimeout,
noteEdit ? this._noteEditTimeout : this._editTimeout,
false,
{
libraries: libraries.map(library => library.libraryID)
libraries: libraries.map(library => library.libraryID),
fileLibraries: [...fileLibraries],
fullTextLibraries: [...fullTextLibraries]
}
);
},

View file

@ -75,6 +75,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
var _delayPromises = [];
var _firstInSession = true;
var _syncInProgress = false;
var _queuedSyncOptions = [];
var _stopping = false;
var _canceller;
var _manualSyncRequired = false; // TODO: make public?
@ -238,6 +239,19 @@ Zotero.Sync.Runner_Module = function (options = {}) {
options.libraries ? Array.from(options.libraries) : []
);
// If file and full-text libraries are specified, limit to libraries we're already
// syncing
var fileLibrariesToSync = new Set(
options.fileLibraries
? options.fileLibraries.filter(id => librariesToSync.includes(id))
: librariesToSync
);
var fullTextLibrariesToSync = new Set(
options.fullTextLibraries
? options.fullTextLibraries.filter(id => librariesToSync.includes(id))
: librariesToSync
);
_stopCheck();
// If items not yet loaded for libraries we need, load them now
@ -268,8 +282,11 @@ Zotero.Sync.Runner_Module = function (options = {}) {
_stopCheck();
// Run file sync on all libraries that passed the last data sync
librariesToSync = yield _doFileSync(nextLibraries, engineOptions);
// Run file sync on all allowed libraries that passed the last data sync
librariesToSync = yield _doFileSync(
nextLibraries.filter(libraryID => fileLibrariesToSync.has(libraryID)),
engineOptions
);
if (librariesToSync.length) {
attempt++;
continue;
@ -277,8 +294,11 @@ Zotero.Sync.Runner_Module = function (options = {}) {
_stopCheck();
// Run full-text sync on all libraries that haven't failed a data sync
librariesToSync = yield _doFullTextSync([...successfulLibraries], engineOptions);
// Run full-text sync on all allowed libraries that haven't failed a data sync
librariesToSync = yield _doFullTextSync(
[...successfulLibraries].filter(libraryID => fullTextLibrariesToSync.has(libraryID)),
engineOptions
);
if (librariesToSync.length) {
attempt++;
continue;
@ -314,6 +334,12 @@ Zotero.Sync.Runner_Module = function (options = {}) {
yield this._sync(options);
return;
}
// If an auto-sync was queued while a sync was ongoing, start again with its options
else if (_queuedSyncOptions.length) {
Zotero.debug("Restarting sync");
yield this._sync(_queuedSyncOptions.shift());
return;
}
Zotero.debug("Done syncing");
Zotero.Notifier.trigger('finish', 'sync', librariesToSync || []);
@ -942,11 +968,13 @@ Zotero.Sync.Runner_Module = function (options = {}) {
if (Zotero.locked) {
Zotero.debug('Zotero is locked -- skipping auto-sync', 4);
_queuedSyncOptions.push(mergedOpts);
return;
}
if (_syncInProgress) {
Zotero.debug('Sync already in progress -- skipping auto-sync', 4);
_queuedSyncOptions.push(mergedOpts);
return;
}
@ -968,6 +996,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
else {
if (_syncInProgress) {
Zotero.debug('Sync in progress -- not setting auto-sync timeout', 4);
_queuedSyncOptions.push(mergedOpts);
return;
}

View file

@ -96,5 +96,23 @@ describe("Zotero.Sync.EventListeners", function () {
mock.verify();
assert.sameMembers(expectation.getCall(0).args[2].libraries, [Zotero.Libraries.userLibraryID]);
});
it("should auto-sync after attachment reindex", async function () {
Zotero.Prefs.set('sync.autoSync', false);
var attachment = await importFileAttachment('test.pdf');
Zotero.Prefs.set('sync.autoSync', true);
var mock = sinon.mock(Zotero.Sync.Runner);
var expectation = mock.expects("setSyncTimeout").once();
await Zotero.Fulltext.indexItems(attachment.id);
await Zotero.Promise.delay(10);
mock.verify();
assert.sameMembers(
expectation.getCall(0).args[2].fullTextLibraries,
[Zotero.Libraries.userLibraryID]
);
});
});
});