commit 88088c68db1215bde94b92c6c91e6d7f258b5e28
parent b72f1c2a08014b74d689a99368f900d996868ddb
Author: Dan Stillman <dstillman@zotero.org>
Date: Sat, 1 Jul 2017 06:26:22 -0400
Add Sync.Storage.Local.updateSyncStates()
This speeds up updating of sync states, particularly after resetting
file sync history.
Diffstat:
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/chrome/content/zotero/xpcom/storage/storageLocal.js b/chrome/content/zotero/xpcom/storage/storageLocal.js
@@ -258,16 +258,26 @@ Zotero.Sync.Storage.Local = {
//Zotero.debug("Memory usage: " + memmgr.resident);
var changed = false;
- for (let i = 0; i < items.length; i++) {
- let item = items[i];
+ var statesToSet = {};
+ for (let item of items) {
// TODO: Catch error?
let state = yield this._checkForUpdatedFile(item, attachmentData[item.id]);
if (state !== false) {
- item.attachmentSyncState = state;
- yield item.saveTx({ skipAll: true });
+ if (!statesToSet[state]) {
+ statesToSet[state] = [];
+ }
+ statesToSet[state].push(item);
changed = true;
}
}
+ // Update sync states in bulk
+ if (changed) {
+ yield Zotero.DB.executeTransaction(function* () {
+ for (let state in statesToSet) {
+ yield this.updateSyncStates(statesToSet[state], parseInt(state));
+ }
+ }.bind(this));
+ }
if (!items.length) {
Zotero.debug("No synced files have changed locally");
@@ -500,6 +510,35 @@ Zotero.Sync.Storage.Local = {
/**
+ * @param {Zotero.Item[]} items
+ * @param {String|Integer} syncState
+ * @return {Promise}
+ */
+ updateSyncStates: function (items, syncState) {
+ if (syncState === undefined) {
+ throw new Error("Sync state not specified");
+ }
+ if (typeof syncState == 'string') {
+ syncState = this["SYNC_STATE_" + syncState.toUpperCase()];
+ }
+ return Zotero.Utilities.Internal.forEachChunkAsync(
+ items,
+ 1000,
+ async function (chunk) {
+ chunk.forEach((item) => {
+ item._attachmentSyncState = syncState;
+ });
+ return Zotero.DB.queryAsync(
+ "UPDATE itemAttachments SET syncState=? WHERE itemID IN "
+ + "(" + chunk.map(item => item.id).join(', ') + ")",
+ syncState
+ );
+ }
+ );
+ },
+
+
+ /**
* Mark all stored files for upload checking
*
* This is used when switching between storage modes in the preferences so that all existing files
diff --git a/test/tests/storageLocalTest.js b/test/tests/storageLocalTest.js
@@ -93,6 +93,28 @@ describe("Zotero.Sync.Storage.Local", function () {
})
})
+ describe("#updateSyncStates()", function () {
+ it("should update attachment sync states to 'to_upload'", function* () {
+ var attachment1 = yield importFileAttachment('test.png');
+ attachment1.attachmentSyncState = 'in_sync';
+ yield attachment1.saveTx();
+ var attachment2 = yield importFileAttachment('test.png');
+ attachment2.attachmentSyncState = 'in_sync';
+ yield attachment2.saveTx();
+
+ var local = Zotero.Sync.Storage.Local;
+ yield local.updateSyncStates([attachment1, attachment2], 'to_upload');
+
+ for (let attachment of [attachment1, attachment2]) {
+ assert.strictEqual(attachment.attachmentSyncState, local.SYNC_STATE_TO_UPLOAD);
+ let state = yield Zotero.DB.valueQueryAsync(
+ "SELECT syncState FROM itemAttachments WHERE itemID=?", attachment.id
+ );
+ assert.strictEqual(state, local.SYNC_STATE_TO_UPLOAD);
+ }
+ });
+ });
+
describe("#resetAllSyncStates()", function () {
it("should reset attachment sync states to 'to_upload'", function* () {
var attachment = yield importFileAttachment('test.png');