Bug 518864 - Persist "next sync time" across events that disable sync
Save a nextSync value in a pref and use it to trigger a sync-on-idle if the "next sync time" already passed when logging in. Make sure to default to backoff time first, then next sync, then use the default.
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -250,16 +250,20 @@ WeaveSvc.prototype = {
set isQuitting(value) { this._isQuitting = value; },
get keyGenEnabled() { return this._keyGenEnabled; },
set keyGenEnabled(value) { this._keyGenEnabled = value; },
get enabled() { return Svc.Prefs.get("enabled"); },
set enabled(value) { Svc.Prefs.set("enabled", value); },
+ // nextSync is in milliseconds, but prefs can't hold that much
+ get nextSync() Svc.Prefs.get("nextSync", 0) * 1000,
+ set nextSync(value) Svc.Prefs.set("nextSync", Math.floor(value / 1000)),
+
get status() { return this._status; },
get locked() { return this._locked; },
lock: function Svc_lock() {
if (this._locked)
return false;
this._locked = true;
return true;
@@ -663,40 +667,28 @@ WeaveSvc.prototype = {
res.authenticator = new NoOpAuthenticator();
res.headers['Content-Type'] = 'application/x-www-form-urlencoded';
let ret = res.post('uid=' + username);
if (ret.indexOf("Further instructions have been sent") >= 0)
return true;
return false;
},
- _autoConnectAttempts: 0,
- _autoConnect: function WeaveSvc__attemptAutoConnect() {
- try {
- if (!this.username || !this.password || !this.passphrase)
- return;
+ _autoConnect: let (attempts = 0) function _autoConnect() {
+ // Can't autoconnect if we're missing these values
+ if (!this.username || !this.password || !this.passphrase)
+ return;
- let failureReason;
- if (Svc.IO.offline)
- failureReason = "Application is offline";
- else if (this.login()) {
- this.syncOnIdle();
- return;
- }
+ // Nothing more to do on a successful login
+ if (this.login())
+ return;
- failureReason = this.status.sync;
- }
- catch (ex) {
- failureReason = ex;
- }
-
- this._autoConnectAttempts++;
- let interval = this._calculateBackoff(this._autoConnectAttempts,
- SCHEDULED_SYNC_INTERVAL);
- this._log.debug("Autoconnect failed: " + failureReason + "; retrying in " +
+ // Something failed, so try again some time later
+ let interval = this._calculateBackoff(++attempts, 60 * 1000);
+ this._log.debug("Autoconnect failed: " + this.status.login + "; retry in " +
Math.ceil(interval / 1000) + " sec.");
Utils.delay(function() this._autoConnect(), interval, this, "_autoTimer");
},
persistLogin: function persistLogin() {
// Canceled master password prompt can prevent these from succeeding
try {
ID.get("WeaveID").persist();
@@ -1035,21 +1027,40 @@ WeaveSvc.prototype = {
IDLE_TIME + " seconds of inactivity.");
Svc.Idle.addIdleObserver(this, IDLE_TIME);
},
/**
* Set a timer for the next sync
*/
_scheduleNextSync: function WeaveSvc__scheduleNextSync(interval) {
- if (!interval)
- interval = this.status.backoffInterval || SCHEDULED_SYNC_INTERVAL;
+ // Figure out when to sync next if not given a interval to wait
+ if (interval == null) {
+ // Make sure we backoff we we need to
+ if (this.status.backoffInterval != 0)
+ interval = this.status.backoffInterval;
+ // Check if we had a pending sync from last time
+ else if (this.nextSync != 0)
+ interval = this.nextSync - Date.now();
+ // Use the default sync interval
+ else
+ interval = SCHEDULED_SYNC_INTERVAL;
+ }
+
+ // Start the sync right away if we're already late
+ if (interval <= 0) {
+ this.syncOnIdle();
+ return;
+ }
this._log.debug("Next sync in " + Math.ceil(interval / 1000) + " sec.");
Utils.delay(function() this.syncOnIdle(), interval, this, "_syncTimer");
+
+ // Save the next sync time in-case sync is disabled (logout/offline/etc.)
+ this.nextSync = Date.now() + interval;
},
_syncErrors: 0,
/**
* Deal with sync errors appropriately
*/
_handleSyncError: function WeaveSvc__handleSyncError() {
this._syncErrors++;
@@ -1094,16 +1105,17 @@ WeaveSvc.prototype = {
// this is a purposeful abort rather than a failure, so don't set
// any status bits
reason = "Can't sync: " + reason;
throw reason;
}
// Clear out any potentially pending syncs now that we're syncing
this._clearSyncTriggers();
+ this.nextSync = 0;
if (!(this._remoteSetup()))
throw "aborting sync, remote setup failed";
// Figure out what the last modified time is for each collection
let info = new Resource(this.infoURL).get();
if (!info.success)
throw "aborting sync, failed to get collections";