Recover from a remotely missing parent collection

This commit is contained in:
Dan Stillman 2017-04-28 03:18:50 -04:00
parent 2db41b0adc
commit fe88530120
2 changed files with 93 additions and 28 deletions

View file

@ -1118,7 +1118,19 @@ Zotero.Sync.Data.Engine.prototype._uploadObjects = Zotero.Promise.coroutine(func
// If an item's dependency is missing remotely and it isn't in the queue (which
// shouldn't happen), mark it as unsynced
if (e.code == 400 || e.code == 409) {
if (objectType == 'item' && data) {
if (data) {
if (objectType == 'collection' && e.code == 409) {
if (data.collection) {
let collection = Zotero.Collections.getByLibraryAndKey(this.libraryID, data.collection);
if (!collection) {
throw new Error(`Collection ${this.libraryID}/${jsonBatch[index].key} `
+ `references parent collection ${data.collection}, which doesn't exist`);
}
Zotero.logError(`Marking collection ${data.collection} as unsynced`);
yield Zotero.Sync.Data.Local.markObjectAsUnsynced(collection);
}
}
else if (objectType == 'item') {
if (data.collection) {
let collection = Zotero.Collections.getByLibraryAndKey(this.libraryID, data.collection);
if (!collection) {
@ -1153,6 +1165,7 @@ Zotero.Sync.Data.Engine.prototype._uploadObjects = Zotero.Promise.coroutine(func
}
}
}
}
// This shouldn't happen, because the upload request includes a library version and should
// prevent an outdated upload before the object version is checked. If it does, we need to

View file

@ -2177,6 +2177,58 @@ describe("Zotero.Sync.Data.Engine", function () {
});
// Note: This shouldn't be necessary, since collections are sorted top-down before uploading
it("should mark local collection as unsynced if it doesn't exist when uploading collection", function* () {
({ engine, client, caller } = yield setup());
var library = Zotero.Libraries.userLibrary;
var libraryID = library.id;
var lastLibraryVersion = 5;
library.libraryVersion = lastLibraryVersion;
yield library.saveTx();
var collection1 = createUnsavedDataObject('collection');
// Set the collection as synced (though this shouldn't happen)
collection1.synced = true;
yield collection1.saveTx();
var collection2 = yield createDataObject('collection', { collections: [collection1.id] });
var called = 0;
server.respond(function (req) {
let requestJSON = JSON.parse(req.requestBody);
if (called == 0) {
assert.lengthOf(requestJSON, 1);
assert.equal(requestJSON[0].key, collection2.key);
req.respond(
200,
{
"Last-Modified-Version": lastLibraryVersion
},
JSON.stringify({
successful: {},
unchanged: {},
failed: {
0: {
code: 409,
message: `Parent collection ${collection1.key} doesn't exist`,
data: {
collection: collection1.key
}
}
}
})
);
}
called++;
});
var e = yield getPromiseError(engine._startUpload());
assert.ok(e);
assert.isFalse(collection1.synced);
});
it("should mark local collection as unsynced if it doesn't exist when uploading item", function* () {
({ engine, client, caller } = yield setup());