Get latest cache object versions in bulk during sync downloads

This commit is contained in:
Dan Stillman 2016-01-12 16:52:25 -05:00
parent 02b29ff14b
commit 02eea99128
3 changed files with 94 additions and 13 deletions

View File

@ -256,15 +256,15 @@ Zotero.Sync.Data.Engine.prototype._startDownload = Zotero.Promise.coroutine(func
+ " modified since last check");
let keys = [];
let versions = yield Zotero.Sync.Data.Local.getLatestCacheObjectVersions(
objectType, this.libraryID, Object.keys(results.versions)
);
for (let key in results.versions) {
// Skip objects that are already up-to-date in the sync cache. Generally all returned
// objects should have newer version numbers, but there are some situations, such as
// full syncs or interrupted syncs, where we may get versions for objects that are
// already up-to-date locally.
let version = yield Zotero.Sync.Data.Local.getLatestCacheObjectVersion(
objectType, this.libraryID, key
);
if (version == results.versions[key]) {
if (versions[key] == results.versions[key]) {
Zotero.debug("Skipping up-to-date " + objectType + " " + this.libraryID + "/" + key);
continue;
}

View File

@ -247,16 +247,33 @@ Zotero.Sync.Data.Local = {
* @return {Promise<Object>} - A promise for an object with object keys as keys and versions
* as properties
*/
getLatestCacheObjectVersions: Zotero.Promise.coroutine(function* (objectType, libraryID) {
var sql = "SELECT key, version FROM syncCache WHERE libraryID=? AND "
+ "syncObjectTypeID IN (SELECT syncObjectTypeID FROM "
+ "syncObjectTypes WHERE name=?) ORDER BY version";
var rows = yield Zotero.DB.queryAsync(sql, [libraryID, objectType]);
getLatestCacheObjectVersions: Zotero.Promise.coroutine(function* (objectType, libraryID, keys=[]) {
var versions = {};
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
versions[row.key] = row.version;
}
yield Zotero.Utilities.Internal.forEachChunkAsync(
keys,
Zotero.DB.MAX_BOUND_PARAMETERS - 2,
Zotero.Promise.coroutine(function* (chunk) {
// The MAX(version) ensures we get the data from the most recent version of the object,
// thanks to SQLite 3.7.11 (http://www.sqlite.org/releaselog/3_7_11.html)
var sql = "SELECT key, MAX(version) AS version FROM syncCache "
+ "WHERE libraryID=? AND "
+ "syncObjectTypeID IN (SELECT syncObjectTypeID FROM syncObjectTypes WHERE name=?) ";
var params = [libraryID, objectType]
if (chunk.length) {
sql += "AND key IN (" + chunk.map(key => '?').join(', ') + ") ";
params = params.concat(chunk);
}
sql += "GROUP BY libraryID, key";
var rows = yield Zotero.DB.queryAsync(sql, params);
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
versions[row.key] = row.version;
}
})
);
return versions;
}),

View File

@ -20,6 +20,70 @@ describe("Zotero.Sync.Data.Local", function() {
})
})
describe("#getLatestCacheObjectVersions", function () {
before(function* () {
yield Zotero.Sync.Data.Local.saveCacheObjects(
'item',
Zotero.Libraries.userLibraryID,
[
{
key: 'AAAAAAAA',
version: 2,
title: "A2"
},
{
key: 'AAAAAAAA',
version: 1,
title: "A1"
},
{
key: 'BBBBBBBB',
version: 1,
title: "B1"
},
{
key: 'BBBBBBBB',
version: 2,
title: "B2"
},
{
key: 'CCCCCCCC',
version: 3,
title: "C"
}
]
);
})
it("should return latest version of all objects if no keys passed", function* () {
var versions = yield Zotero.Sync.Data.Local.getLatestCacheObjectVersions(
'item',
Zotero.Libraries.userLibraryID
);
var keys = Object.keys(versions);
assert.lengthOf(keys, 3);
assert.sameMembers(keys, ['AAAAAAAA', 'BBBBBBBB', 'CCCCCCCC']);
assert.equal(versions.AAAAAAAA, 2);
assert.equal(versions.BBBBBBBB, 2);
assert.equal(versions.CCCCCCCC, 3);
})
it("should return latest version of objects with passed keys", function* () {
var versions = yield Zotero.Sync.Data.Local.getLatestCacheObjectVersions(
'item',
Zotero.Libraries.userLibraryID,
['AAAAAAAA', 'CCCCCCCC']
);
var keys = Object.keys(versions);
assert.lengthOf(keys, 2);
assert.sameMembers(keys, ['AAAAAAAA', 'CCCCCCCC']);
assert.equal(versions.AAAAAAAA, 2);
assert.equal(versions.CCCCCCCC, 3);
})
})
describe("#processSyncCacheForObjectType()", function () {
var types = Zotero.DataObjectUtilities.getTypes();