Bug 692700 part 1 - Set X-If-Unmodified-Since when uploading meta/global. r=markh
authorEdouard Oger <eoger@fastmail.com>
Tue, 14 Mar 2017 14:42:24 -0400
changeset 348988 bf5d88ce5097
parent 348987 f48e43c2ac77
child 348989 8c9589795211
push id31541
push usercbook@mozilla.com
push dateThu, 23 Mar 2017 12:43:04 +0000
treeherdermozilla-central@89b93d310da5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarkh
bugs692700
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 692700 part 1 - Set X-If-Unmodified-Since when uploading meta/global. r=markh MozReview-Commit-ID: IoiThiDlvCj
services/sync/modules/service.js
--- 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();
   },