Recover from a remotely missing parent collection
This commit is contained in:
parent
2db41b0adc
commit
fe88530120
2 changed files with 93 additions and 28 deletions
|
@ -1118,37 +1118,50 @@ 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
|
// If an item's dependency is missing remotely and it isn't in the queue (which
|
||||||
// shouldn't happen), mark it as unsynced
|
// shouldn't happen), mark it as unsynced
|
||||||
if (e.code == 400 || e.code == 409) {
|
if (e.code == 400 || e.code == 409) {
|
||||||
if (objectType == 'item' && data) {
|
if (data) {
|
||||||
if (data.collection) {
|
if (objectType == 'collection' && e.code == 409) {
|
||||||
let collection = Zotero.Collections.getByLibraryAndKey(this.libraryID, data.collection);
|
if (data.collection) {
|
||||||
if (!collection) {
|
let collection = Zotero.Collections.getByLibraryAndKey(this.libraryID, data.collection);
|
||||||
throw new Error(`Item ${this.libraryID}/${jsonBatch[index].key} `
|
if (!collection) {
|
||||||
+ `references collection ${data.collection}, which doesn't exist`);
|
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);
|
||||||
}
|
}
|
||||||
Zotero.logError(`Marking collection ${data.collection} as unsynced`);
|
|
||||||
yield Zotero.Sync.Data.Local.markObjectAsUnsynced(collection);
|
|
||||||
}
|
}
|
||||||
else if (data.parentItem) {
|
else if (objectType == 'item') {
|
||||||
let parentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, data.parentItem);
|
if (data.collection) {
|
||||||
if (!parentItem) {
|
let collection = Zotero.Collections.getByLibraryAndKey(this.libraryID, data.collection);
|
||||||
throw new Error(`Item ${this.libraryID}/${jsonBatch[index].key} references parent `
|
if (!collection) {
|
||||||
+ `item ${data.parentItem}, which doesn't exist`);
|
throw new Error(`Item ${this.libraryID}/${jsonBatch[index].key} `
|
||||||
|
+ `references collection ${data.collection}, which doesn't exist`);
|
||||||
|
}
|
||||||
|
Zotero.logError(`Marking collection ${data.collection} as unsynced`);
|
||||||
|
yield Zotero.Sync.Data.Local.markObjectAsUnsynced(collection);
|
||||||
}
|
}
|
||||||
|
else if (data.parentItem) {
|
||||||
let id = parentItem.id;
|
let parentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, data.parentItem);
|
||||||
// If parent item isn't already in queue, mark it as unsynced and add it
|
if (!parentItem) {
|
||||||
if (!queue.find(o => o.id == id) && !batch.find(o => o.id == id)) {
|
throw new Error(`Item ${this.libraryID}/${jsonBatch[index].key} references parent `
|
||||||
yield Zotero.Sync.Data.Local.markObjectAsUnsynced(parentItem);
|
+ `item ${data.parentItem}, which doesn't exist`);
|
||||||
Zotero.logError(`Adding parent item ${data.parentItem} to upload queue`);
|
}
|
||||||
queue.push({
|
|
||||||
id,
|
let id = parentItem.id;
|
||||||
json: null,
|
// If parent item isn't already in queue, mark it as unsynced and add it
|
||||||
tries: 0,
|
if (!queue.find(o => o.id == id) && !batch.find(o => o.id == id)) {
|
||||||
failed: false
|
yield Zotero.Sync.Data.Local.markObjectAsUnsynced(parentItem);
|
||||||
});
|
Zotero.logError(`Adding parent item ${data.parentItem} to upload queue`);
|
||||||
// Pretend that we were successful so syncing continues
|
queue.push({
|
||||||
numSuccessful++;
|
id,
|
||||||
continue;
|
json: null,
|
||||||
|
tries: 0,
|
||||||
|
failed: false
|
||||||
|
});
|
||||||
|
// Pretend that we were successful so syncing continues
|
||||||
|
numSuccessful++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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* () {
|
it("should mark local collection as unsynced if it doesn't exist when uploading item", function* () {
|
||||||
({ engine, client, caller } = yield setup());
|
({ engine, client, caller } = yield setup());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue