Bug 692700 part 1 - Set X-If-Unmodified-Since when uploading meta/global. r?markh
MozReview-Commit-ID: IoiThiDlvCj
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -897,26 +897,19 @@ Sync11Service.prototype = {
if (this.recordManager.response.status == 401) {
this._log.debug("Fetching meta/global record on the server returned 401.");
this.errorHandler.checkServerError(this.recordManager.response);
return false;
}
if (this.recordManager.response.status == 404) {
this._log.debug("No meta/global record on the server. Creating one.");
- newMeta = new WBORecord("meta", "global");
- newMeta.payload.syncID = this.syncID;
- newMeta.payload.storageVersion = STORAGE_VERSION;
- newMeta.payload.declined = this.engineManager.getDeclined();
-
- newMeta.isNew = true;
-
- this.recordManager.set(this.metaURL, newMeta);
- let uploadRes = newMeta.upload(this.resource(this.metaURL));
- if (!uploadRes.success) {
+ try {
+ this._uploadNewMetaGlobal();
+ } catch (uploadRes) {
this._log.warn("Unable to upload new meta/global. Failing remote setup.");
this.errorHandler.checkServerError(uploadRes);
return false;
}
} else if (!newMeta) {
this._log.warn("Unable to get meta/global. Failing remote setup.");
this.errorHandler.checkServerError(this.recordManager.response);
return false;
@@ -1111,53 +1104,63 @@ Sync11Service.prototype = {
}
this.uploadMetaGlobal(meta);
}
}))();
},
/**
- * Upload meta/global, throwing the response on failure.
+ * Upload a fresh meta/global record
+ * @throws the response object if the upload request was not a success
+ */
+ _uploadNewMetaGlobal() {
+ let meta = new WBORecord("meta", "global");
+ meta.payload.syncID = this.syncID;
+ meta.payload.storageVersion = STORAGE_VERSION;
+ meta.payload.declined = this.engineManager.getDeclined();
+ meta.modified = 0;
+ meta.isNew = true;
+
+ this.uploadMetaGlobal(meta);
+ },
+
+ /**
+ * Upload meta/global, throwing the response on failure
+ * @param {WBORecord} meta meta/global record
+ * @throws the response object if the request was not a success
*/
uploadMetaGlobal(meta) {
- this._log.debug("Uploading meta/global: " + JSON.stringify(meta));
-
- // It would be good to set the X-If-Unmodified-Since header to `timestamp`
- // for this PUT to ensure at least some level of transactionality.
- // Unfortunately, the servers don't support it after a wipe right now
- // (bug 693893), so we're going to defer this until bug 692700.
+ this._log.debug("Uploading meta/global", meta);
let res = this.resource(this.metaURL);
+ res.setHeader("X-If-Unmodified-Since", meta.modified);
let response = res.put(meta);
if (!response.success) {
throw response;
}
+ // From https://docs.services.mozilla.com/storage/apis-1.5.html:
+ // "Successful responses will return the new last-modified time for the collection."
+ meta.modified = response.obj;
this.recordManager.set(this.metaURL, meta);
},
_freshStart: function _freshStart() {
this._log.info("Fresh start. Resetting client.");
this.resetClient();
this.collectionKeys.clear();
// Wipe the server.
this.wipeServer();
// Upload a new meta/global record.
- let meta = new WBORecord("meta", "global");
- meta.payload.syncID = this.syncID;
- meta.payload.storageVersion = STORAGE_VERSION;
- meta.payload.declined = this.engineManager.getDeclined();
- meta.isNew = true;
-
- // uploadMetaGlobal throws on failure -- including race conditions.
+ // _uploadNewMetaGlobal throws on failure -- including race conditions.
// If we got into a race condition, we'll abort the sync this way, too.
// That's fine. We'll just wait till the next sync. The client that we're
// racing is probably busy uploading stuff right now anyway.
- this.uploadMetaGlobal(meta);
+ this._uploadNewMetaGlobal();
// Wipe everything we know about except meta because we just uploaded it
// TODO: there's a bug here. We should be calling resetClient, no?
// Generate, upload, and download new keys. Do this last so we don't wipe
// them...
this.generateNewSymmetricKeys();
},