- Add triggers for full sync on various errors
- Add Zotero.Error(message, error) constructor to create a throwable error object with an error code - Allow only one automatic client reset between manual syncs - Fix "Source item for keyed source doesn't exist in Zotero.Item.getSource()" error - Object produced by item.serialize() now contains .sourceItemKey instead of .sourceItemID - Better error logging for missing XPCOM files
This commit is contained in:
parent
46209bd4f3
commit
41437738b0
5 changed files with 110 additions and 44 deletions
|
@ -1016,7 +1016,9 @@ Zotero.Collection.prototype._getParent = function() {
|
|||
}
|
||||
var parentCollection = Zotero.Collections.getByLibraryAndKey(this.libraryID, this._parent);
|
||||
if (!parentCollection) {
|
||||
throw ("Parent collection for keyed parent doesn't exist in Zotero.Collection._getParent()");
|
||||
var msg = "Parent collection for keyed parent doesn't exist in Zotero.Collection._getParent()";
|
||||
var e = new Zotero.Error(msg, "MISSING_OBJECT");
|
||||
throw (e);
|
||||
}
|
||||
// Replace stored key with id
|
||||
this._parent = parentCollection.id;
|
||||
|
|
|
@ -1380,8 +1380,10 @@ Zotero.Item.prototype.save = function() {
|
|||
}
|
||||
|
||||
var newSourceItemNotifierData = {};
|
||||
newSourceItemNotifierData[newSourceItem.id] =
|
||||
{ old: newSourceItem.serialize() };
|
||||
newSourceItemNotifierData[newSourceItem.id] = {
|
||||
old: newSourceItem.serialize()
|
||||
};
|
||||
Zotero.Notifier.trigger('modify', 'item', newSourceItem.id, newSourceItemNotifierData);
|
||||
|
||||
switch (Zotero.ItemTypes.getName(this.itemTypeID)) {
|
||||
case 'note':
|
||||
|
@ -1752,24 +1754,28 @@ Zotero.Item.prototype.save = function() {
|
|||
|
||||
if (newSourceItem) {
|
||||
var newSourceItemNotifierData = {};
|
||||
newSourceItemNotifierData[newSourceItem.id] =
|
||||
{ old: newSourceItem.serialize() };
|
||||
newSourceItemNotifierData[newSourceItem.id] = {
|
||||
old: newSourceItem.serialize()
|
||||
};
|
||||
Zotero.Notifier.trigger('modify', 'item', newSourceItem.id, newSourceItemNotifierData);
|
||||
}
|
||||
|
||||
if (this._previousData) {
|
||||
var oldSourceItemID = this._previousData.sourceItemID;
|
||||
if (oldSourceItemID) {
|
||||
var oldSourceItem = Zotero.Items.get(oldSourceItemID);
|
||||
var oldSourceItemKey = this._previousData.sourceItemKey;
|
||||
if (oldSourceItemKey) {
|
||||
var oldSourceItem = Zotero.Items.getByKey(this.libraryID, oldSourceItemKey);
|
||||
}
|
||||
if (oldSourceItem) {
|
||||
var oldSourceItemNotifierData = {};
|
||||
oldSourceItemNotifierData[oldSourceItem.id] =
|
||||
{ old: oldSourceItem.serialize() };
|
||||
oldSourceItemNotifierData[oldSourceItem.id] = {
|
||||
old: oldSourceItem.serialize()
|
||||
};
|
||||
Zotero.Notifier.trigger('modify', 'item', oldSourceItem.id, oldSourceItemNotifierData);
|
||||
}
|
||||
else if (oldSourceItemID) {
|
||||
else if (oldSourceItemKey) {
|
||||
var oldSourceItemNotifierData = null;
|
||||
Zotero.debug("Old source item " + oldSourceItemID
|
||||
+ " didn't exist in setSource()", 2);
|
||||
Zotero.debug("Old source item " + oldSourceItemKey
|
||||
+ " didn't exist in Zotero.Item.save()", 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1777,7 +1783,7 @@ Zotero.Item.prototype.save = function() {
|
|||
// If this was an independent item, remove from any collections
|
||||
// where it existed previously and add source instead if
|
||||
// there is one
|
||||
if (!oldSourceItemID) {
|
||||
if (!oldSourceItemKey) {
|
||||
var sql = "SELECT collectionID FROM collectionItems "
|
||||
+ "WHERE itemID=?";
|
||||
var changedCollections = Zotero.DB.columnQuery(sql, this.id);
|
||||
|
@ -1946,15 +1952,6 @@ Zotero.Item.prototype.save = function() {
|
|||
Zotero.Notifier.trigger('modify', 'item', this.id, { old: this._previousData });
|
||||
}
|
||||
|
||||
if (oldSourceItem) {
|
||||
Zotero.Notifier.trigger('modify', 'item',
|
||||
oldSourceItemID, oldSourceItemNotifierData);
|
||||
}
|
||||
if (newSourceItem) {
|
||||
Zotero.Notifier.trigger('modify', 'item',
|
||||
newSourceItem.id, newSourceItemNotifierData);
|
||||
}
|
||||
|
||||
if (isNew) {
|
||||
var id = this.id;
|
||||
this._disabled = true;
|
||||
|
@ -2003,7 +2000,9 @@ Zotero.Item.prototype.getSource = function() {
|
|||
}
|
||||
var sourceItem = Zotero.Items.getByLibraryAndKey(this.libraryID, this._sourceItem);
|
||||
if (!sourceItem) {
|
||||
throw ("Source item for keyed source doesn't exist in Zotero.Item.getSource()");
|
||||
var msg = "Source item for keyed source doesn't exist in Zotero.Item.getSource()";
|
||||
var e = new Zotero.Error(msg, "MISSING_OBJECT");
|
||||
throw (e);
|
||||
}
|
||||
// Replace stored key with id
|
||||
this._sourceItem = sourceItem.id;
|
||||
|
@ -3836,9 +3835,9 @@ Zotero.Item.prototype.toArray = function (mode) {
|
|||
// Notes
|
||||
if (this.isNote()) {
|
||||
arr.note = this.getNote();
|
||||
var parent = this.getSource();
|
||||
var parent = this.getSourceKey();
|
||||
if (parent) {
|
||||
arr.sourceItemID = parent;
|
||||
arr.sourceItemKey = parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3847,9 +3846,9 @@ Zotero.Item.prototype.toArray = function (mode) {
|
|||
// Attachments can have embedded notes
|
||||
arr.note = this.getNote();
|
||||
|
||||
var parent = this.getSource();
|
||||
var parent = this.getSourceKey();
|
||||
if (parent) {
|
||||
arr.sourceItemID = parent;
|
||||
arr.sourceItemKey = parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4005,9 +4004,9 @@ Zotero.Item.prototype.serialize = function(mode) {
|
|||
}
|
||||
|
||||
arr.note = this.getNote();
|
||||
var parent = this.getSource();
|
||||
var parent = this.getSourceKey();
|
||||
if (parent) {
|
||||
arr.sourceItemID = parent;
|
||||
arr.sourceItemKey = parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
chrome/content/zotero/xpcom/error.js
Normal file
17
chrome/content/zotero/xpcom/error.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
Zotero.Error = function (message, error) {
|
||||
this.name = "ZOTERO_ERROR";
|
||||
this.message = message;
|
||||
if (parseInt(error) == error) {
|
||||
this.error = error;
|
||||
}
|
||||
else {
|
||||
this.error = Zotero.Error["ERROR_" + error] ? Zotero.Error["ERROR_" + error] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.Error.ERROR_UNKNOWN = 0;
|
||||
Zotero.Error.ERROR_MISSING_OBJECT = 1;
|
||||
|
||||
Zotero.Error.prototype.toString = function () {
|
||||
return this.message;
|
||||
}
|
|
@ -837,6 +837,7 @@ Zotero.Sync.Server = new function () {
|
|||
var _sessionID;
|
||||
var _sessionLock;
|
||||
var _throttleTimeout;
|
||||
var _canAutoResetClient = true;
|
||||
|
||||
function login(callback, callbackCallback) {
|
||||
var url = _serverURL + "login";
|
||||
|
@ -1356,6 +1357,8 @@ Zotero.Sync.Server = new function () {
|
|||
|
||||
|
||||
function resetClient() {
|
||||
Zotero.debug("Resetting client");
|
||||
|
||||
Zotero.DB.beginTransaction();
|
||||
|
||||
var sql = "DELETE FROM version WHERE schema IN "
|
||||
|
@ -1498,11 +1501,20 @@ Zotero.Sync.Server = new function () {
|
|||
break;
|
||||
|
||||
case 'FULL_SYNC_REQUIRED':
|
||||
Zotero.DB.rollbackAllTransactions();
|
||||
// Let current sync fail, and then do a full sync
|
||||
var background = Zotero.Sync.Runner.background;
|
||||
setTimeout(function () {
|
||||
if (Zotero.Prefs.get('sync.debugNoAutoResetClient')) {
|
||||
Components.utils.reportError("Skipping automatic client reset due to debug pref");
|
||||
return;
|
||||
}
|
||||
if (!Zotero.Sync.Server.canAutoResetClient) {
|
||||
Components.utils.reportError("Client has already been auto-reset in Zotero.Sync.Server._checkResponse() -- manual sync required");
|
||||
return;
|
||||
}
|
||||
|
||||
Zotero.Sync.Server.resetClient();
|
||||
Zotero.Sync.Server.canAutoResetClient = false;
|
||||
Zotero.Sync.Runner.sync(background);
|
||||
}, 1);
|
||||
break;
|
||||
|
@ -1511,8 +1523,6 @@ Zotero.Sync.Server = new function () {
|
|||
if (!Zotero.Sync.Runner.background) {
|
||||
var tag = xmlhttp.responseXML.firstChild.getElementsByTagName('tag');
|
||||
if (tag.length) {
|
||||
Zotero.DB.rollbackAllTransactions();
|
||||
|
||||
var tag = tag[0].firstChild.nodeValue;
|
||||
setTimeout(function () {
|
||||
var callback = function () {
|
||||
|
@ -1667,6 +1677,28 @@ Zotero.Sync.Server = new function () {
|
|||
|
||||
|
||||
function _error(e, extraInfo) {
|
||||
if (e.name && e.name == 'ZOTERO_ERROR') {
|
||||
switch (e.error) {
|
||||
case Zotero.Error.ERROR_MISSING_OBJECT:
|
||||
// Let current sync fail, and then do a full sync
|
||||
var background = Zotero.Sync.Runner.background;
|
||||
setTimeout(function () {
|
||||
if (Zotero.Prefs.get('sync.debugNoAutoResetClient')) {
|
||||
Components.utils.reportError("Skipping automatic client reset due to debug pref");
|
||||
return;
|
||||
}
|
||||
if (!Zotero.Sync.Server.canAutoResetClient) {
|
||||
Components.utils.reportError("Client has already been auto-reset in Zotero.Sync.Server._error() -- manual sync required");
|
||||
return;
|
||||
}
|
||||
Zotero.Sync.Server.resetClient();
|
||||
Zotero.Sync.Server.canAutoResetClient = false;
|
||||
Zotero.Sync.Runner.sync(background);
|
||||
}, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (extraInfo) {
|
||||
// Server errors will generally be HTML
|
||||
extraInfo = Zotero.Utilities.prototype.unescapeHTML(extraInfo);
|
||||
|
@ -1685,7 +1717,7 @@ Zotero.Sync.Server = new function () {
|
|||
|
||||
Zotero.Sync.Runner.setError(e.message ? e.message : e);
|
||||
Zotero.Sync.Runner.reset();
|
||||
throw(e);
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3001,9 +3033,11 @@ Zotero.Sync.Server.Data = new function() {
|
|||
// the item's creator block, where a copy should be provided
|
||||
if (!creatorObj) {
|
||||
if (creator.creator.length() == 0) {
|
||||
throw ("Data for missing local creator "
|
||||
var msg = "Data for missing local creator "
|
||||
+ data.libraryID + "/" + creator.@key.toString()
|
||||
+ " not provided in Zotero.Sync.Server.Data.xmlToItem()");
|
||||
+ " not provided in Zotero.Sync.Server.Data.xmlToItem()";
|
||||
var e = new Zotero.Error(msg, "MISSING_OBJECT");
|
||||
throw (e);
|
||||
}
|
||||
var l = creator.@libraryID.toString();
|
||||
l = l ? l : null;
|
||||
|
@ -3054,8 +3088,10 @@ Zotero.Sync.Server.Data = new function() {
|
|||
for each(var key in related) {
|
||||
var relItem = Zotero.Items.getByLibraryAndKey(item.libraryID, key);
|
||||
if (!relItem) {
|
||||
throw ("Related item " + item.libraryID + "/" + key
|
||||
+ " doesn't exist in Zotero.Sync.Server.Data.xmlToItem()");
|
||||
var msg = "Related item " + item.libraryID + "/" + key
|
||||
+ " doesn't exist in Zotero.Sync.Server.Data.xmlToItem()";
|
||||
var e = new Zotero.Error(msg, "MISSING_OBJECT");
|
||||
throw (e);
|
||||
}
|
||||
relatedIDs.push(relItem.id);
|
||||
}
|
||||
|
@ -3172,8 +3208,11 @@ Zotero.Sync.Server.Data = new function() {
|
|||
for each(var key in childItems) {
|
||||
var childItem = Zotero.Items.getByLibraryAndKey(collection.libraryID, key);
|
||||
if (!childItem) {
|
||||
throw ("Missing child item " + key + " for collection " + collection.libraryID + "/" + collection.key
|
||||
+ " in Zotero.Sync.Server.Data.xmlToCollection()");
|
||||
var msg = "Missing child item " + key + " for collection "
|
||||
+ collection.libraryID + "/" + collection.key
|
||||
+ " in Zotero.Sync.Server.Data.xmlToCollection()";
|
||||
var e = new Zotero.Error(msg, "MISSING_OBJECT");
|
||||
throw (e);
|
||||
}
|
||||
childItemIDs.push(childItem.id);
|
||||
}
|
||||
|
@ -3446,7 +3485,9 @@ Zotero.Sync.Server.Data = new function() {
|
|||
for each(var key in keys) {
|
||||
var item = Zotero.Items.getByLibraryAndKey(tag.libraryID, key);
|
||||
if (!item) {
|
||||
throw ("Linked item " + key + " doesn't exist in Zotero.Sync.Server.Data.xmlToTag()");
|
||||
var msg = "Linked item " + key + " doesn't exist in Zotero.Sync.Server.Data.xmlToTag()";
|
||||
var e = new Zotero.Error(msg, "MISSING_OBJECT");
|
||||
throw (e);
|
||||
}
|
||||
ids.push(item.id);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ var xpcomFiles = [
|
|||
'db',
|
||||
'duplicate',
|
||||
'enstyle',
|
||||
'error',
|
||||
'file',
|
||||
'fulltext',
|
||||
'id',
|
||||
|
@ -68,9 +69,15 @@ var xpcomFiles = [
|
|||
];
|
||||
|
||||
for (var i=0; i<xpcomFiles.length; i++) {
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://zotero/content/xpcom/" + xpcomFiles[i] + ".js");
|
||||
try {
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://zotero/content/xpcom/" + xpcomFiles[i] + ".js");
|
||||
}
|
||||
catch (e) {
|
||||
Components.utils.reportError("Error loading " + xpcomFiles[i] + ".js");
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue