Bug 1243856 - Remove alarms from the Push H2 backend. r=dragana
authorKit Cambridge <kcambridge@mozilla.com>
Wed, 03 Feb 2016 18:16:10 -0800
changeset 323144 af9a9799032d6cdff853c70b9524ecc89096f590
parent 323143 e58bd4bbf964582adf486733fc9c46e47c2ef277
child 323145 1cfb0f3e893ebe7fe0979b3f74b3dac4b7bb7752
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1243856
milestone47.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 1243856 - Remove alarms from the Push H2 backend. r=dragana MozReview-Commit-ID: LZJY0DtLE4E
dom/push/PushService.jsm
dom/push/PushServiceHttp2.jsm
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -19,19 +19,16 @@ Cu.import("resource://gre/modules/Promis
 
 const {PushServiceWebSocket} = Cu.import("resource://gre/modules/PushServiceWebSocket.jsm");
 const {PushServiceHttp2} = Cu.import("resource://gre/modules/PushServiceHttp2.jsm");
 const {PushCrypto} = Cu.import("resource://gre/modules/PushCrypto.jsm");
 
 // Currently supported protocols: WebSocket.
 const CONNECTION_PROTOCOLS = [PushServiceWebSocket, PushServiceHttp2];
 
-XPCOMUtils.defineLazyModuleGetter(this, "AlarmService",
-                                  "resource://gre/modules/AlarmService.jsm");
-
 XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
                                    "@mozilla.org/contentsecuritymanager;1",
                                    "nsIContentSecurityManager");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gPushNotifier",
                                    "@mozilla.org/push/Notifier;1",
                                    "nsIPushNotifier");
 
@@ -91,17 +88,16 @@ const UNINIT_EVENT = 3;
  * (PushServiceWebSocket) to communicate with the server and PushDB (IndexedDB)
  * for persistence.
  */
 this.PushService = {
   _service: null,
   _state: PUSH_SERVICE_UNINIT,
   _db: null,
   _options: null,
-  _alarmID: null,
   _visibleNotifications: new Map(),
 
   // Callback that is called after attempting to
   // reduce the quota for a record. Used for testing purposes.
   _updateQuotaTestCallback: null,
 
   // When serverURI changes (this is used for testing), db is cleaned up and a
   // a new db is started. This events must be sequential.
@@ -543,23 +539,21 @@ this.PushService = {
    */
   _stopService: function(event) {
     console.debug("stopService()");
 
     if (this._state < PUSH_SERVICE_ACTIVATING) {
       return;
     }
 
-    this.stopAlarm();
     this._stopObservers();
 
     this._service.disconnect();
     this._service.uninit();
     this._service = null;
-    this.stopAlarm();
 
     if (!this._db) {
       return Promise.resolve();
     }
     if (event == UNINIT_EVENT) {
       // If it is uninitialized just close db.
       this._db.close();
       this._db = null;
@@ -604,67 +598,16 @@ this.PushService = {
     this._stateChangeProcessEnqueue(_ =>
       {
         this._changeServerURL("", UNINIT_EVENT);
         this._setState(PUSH_SERVICE_UNINIT);
         console.debug("uninit: shutdown complete!");
       });
   },
 
-  /** |delay| should be in milliseconds. */
-  setAlarm: function(delay) {
-    if (this._state <= PUSH_SERVICE_ACTIVATING) {
-      return;
-    }
-
-    // Bug 909270: Since calls to AlarmService.add() are async, calls must be
-    // 'queued' to ensure only one alarm is ever active.
-    if (this._settingAlarm) {
-        // onSuccess will handle the set. Overwriting the variable enforces the
-        // last-writer-wins semantics.
-        this._queuedAlarmDelay = delay;
-        this._waitingForAlarmSet = true;
-        return;
-    }
-
-    // Stop any existing alarm.
-    this.stopAlarm();
-
-    this._settingAlarm = true;
-    AlarmService.add(
-      {
-        date: new Date(Date.now() + delay),
-        ignoreTimezone: true
-      },
-      () => {
-        if (this._state > PUSH_SERVICE_ACTIVATING) {
-          this._service.onAlarmFired();
-        }
-      }, (alarmID) => {
-        this._alarmID = alarmID;
-        console.debug("setAlarm: Set alarm", delay, "in the future",
-          this._alarmID);
-        this._settingAlarm = false;
-
-        if (this._waitingForAlarmSet) {
-          this._waitingForAlarmSet = false;
-          this.setAlarm(this._queuedAlarmDelay);
-        }
-      }
-    );
-  },
-
-  stopAlarm: function() {
-    if (this._alarmID !== null) {
-      console.debug("stopAlarm: Stopped existing alarm", this._alarmID);
-      AlarmService.remove(this._alarmID);
-      this._alarmID = null;
-    }
-  },
-
   /**
    * Drops all active registrations and notifies the associated service
    * workers. This function is called when the user switches Push servers,
    * or when the server invalidates all existing registrations.
    *
    * We ignore expired registrations because they're already handled in other
    * code paths. Registrations that expired after exceeding their quotas are
    * evicted at startup, or on the next `idle-daily` event. Registrations that
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -460,17 +460,17 @@ this.PushServiceHttp2 = {
         result.p256dhPublicKey = publicKey;
         result.p256dhPrivateKey = privateKey;
         result.authenticationSecret = PushCrypto.generateAuthenticationSecret();
         this._conns[result.subscriptionUri] = {
           channel: null,
           listener: null,
           countUnableToConnect: 0,
           lastStartListening: 0,
-          waitingForAlarm: false
+          retryTimerID: 0,
         };
         this._listenForMsgs(result.subscriptionUri);
         return result;
       })
     );
   },
 
   _subscribeResourceInternal: function(aSubInfo) {
@@ -578,38 +578,30 @@ this.PushServiceHttp2 = {
     if (this._conns[aSubscriptionUri].countUnableToConnect >= maxRetries) {
       this._shutdownSubscription(aSubscriptionUri);
       this._resubscribe(aSubscriptionUri);
       return;
     }
 
     if (retryAfter !== -1) {
       // This is a 5xx response.
-      // To respect RetryAfter header, setTimeout is used. setAlarm sets a
-      // cumulative alarm so it will not always respect RetryAfter header.
       this._conns[aSubscriptionUri].countUnableToConnect++;
-      setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
+      this._conns[aSubscriptionUri].retryTimerID =
+        setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
       return;
     }
 
-    // we set just one alarm because most probably all connection will go over
-    // a single TCP connection.
     retryAfter = prefs.get("http2.retryInterval") *
       Math.pow(2, this._conns[aSubscriptionUri].countUnableToConnect);
 
     retryAfter = retryAfter * (0.8 + Math.random() * 0.4); // add +/-20%.
 
     this._conns[aSubscriptionUri].countUnableToConnect++;
-
-    if (retryAfter === 0) {
-      setTimeout(_ => this._listenForMsgs(aSubscriptionUri), 0);
-    } else {
-      this._conns[aSubscriptionUri].waitingForAlarm = true;
-      this._mainPushService.setAlarm(retryAfter);
-    }
+    this._conns[aSubscriptionUri].retryTimerID =
+      setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
 
     console.debug("retryAfterBackoff: Retry in", retryAfter);
   },
 
   // Close connections.
   _shutdownConnections: function(deleteInfo) {
     console.debug("shutdownConnections()");
 
@@ -621,17 +613,21 @@ this.PushServiceHttp2 = {
 
         if (this._conns[subscriptionUri].channel) {
           try {
             this._conns[subscriptionUri].channel.cancel(Cr.NS_ERROR_ABORT);
           } catch (e) {}
         }
         this._conns[subscriptionUri].listener = null;
         this._conns[subscriptionUri].channel = null;
-        this._conns[subscriptionUri].waitingForAlarm = false;
+
+        if (this._conns[subscriptionUri].retryTimerID > 0) {
+          clearTimeout(this._conns[subscriptionUri].retryTimerID);
+        }
+
         if (deleteInfo) {
           delete this._conns[subscriptionUri];
         }
       }
     }
   },
 
   // Start listening if subscriptions present.
@@ -650,37 +646,23 @@ this.PushServiceHttp2 = {
   },
 
   _startSingleConnection: function(record) {
     console.debug("_startSingleConnection()");
     if (typeof this._conns[record.subscriptionUri] != "object") {
       this._conns[record.subscriptionUri] = {channel: null,
                                              listener: null,
                                              countUnableToConnect: 0,
-                                             waitingForAlarm: false};
+                                             retryTimerID: 0};
     }
     if (!this._conns[record.subscriptionUri].conn) {
-      this._conns[record.subscriptionUri].waitingForAlarm = false;
       this._listenForMsgs(record.subscriptionUri);
     }
   },
 
-  // Start listening if subscriptions present.
-  _startConnectionsWaitingForAlarm: function() {
-    console.debug("startConnectionsWaitingForAlarm()");
-    for (let subscriptionUri in this._conns) {
-      if ((this._conns[subscriptionUri]) &&
-          !this._conns[subscriptionUri].conn &&
-          this._conns[subscriptionUri].waitingForAlarm) {
-        this._conns[subscriptionUri].waitingForAlarm = false;
-        this._listenForMsgs(subscriptionUri);
-      }
-    }
-  },
-
   // Close connection and notify apps that subscription are gone.
   _shutdownSubscription: function(aSubscriptionUri) {
     console.debug("shutdownSubscriptions()");
 
     if (typeof this._conns[aSubscriptionUri] == "object") {
       if (this._conns[aSubscriptionUri].listener) {
         this._conns[aSubscriptionUri].listener._pushService = null;
       }
@@ -780,20 +762,16 @@ this.PushServiceHttp2 = {
       }
     )
     .then(_ => this._ackMsgRecv(aAckUri))
     .catch(err => {
       console.error("pushChannelOnStop: Error receiving message",
         err);
     });
   },
-
-  onAlarmFired: function() {
-    this._startConnectionsWaitingForAlarm();
-  },
 };
 
 function PushRecordHttp2(record) {
   PushRecord.call(this, record);
   this.subscriptionUri = record.subscriptionUri;
   this.pushReceiptEndpoint = record.pushReceiptEndpoint;
 }