зеркало из https://github.com/mozilla/gecko-dev.git
bug 497938 - Client should back off server when it is busy, r=edilee
--HG-- extra : rebase_source : 347137310b0ff0bba8b5267632259645c516e56b
This commit is contained in:
Родитель
da26bc9eee
Коммит
2947c8e012
|
@ -55,6 +55,9 @@ const Cu = Components.utils;
|
||||||
// How long we wait between sync checks.
|
// How long we wait between sync checks.
|
||||||
const SCHEDULED_SYNC_INTERVAL = 60 * 1000 * 5; // five minutes
|
const SCHEDULED_SYNC_INTERVAL = 60 * 1000 * 5; // five minutes
|
||||||
|
|
||||||
|
// how long we should wait before actually syncing on idle
|
||||||
|
const IDLE_TIME = 5; // xxxmpc: in seconds, should be preffable
|
||||||
|
|
||||||
// INITIAL_THRESHOLD represents the value an engine's score has to exceed
|
// INITIAL_THRESHOLD represents the value an engine's score has to exceed
|
||||||
// in order for us to sync it the first time we start up (and the first time
|
// in order for us to sync it the first time we start up (and the first time
|
||||||
// we do a sync check after having synced the engine or reset the threshold).
|
// we do a sync check after having synced the engine or reset the threshold).
|
||||||
|
@ -317,6 +320,8 @@ WeaveSvc.prototype = {
|
||||||
Svc.Observer.addObserver(this, "network:offline-status-changed", true);
|
Svc.Observer.addObserver(this, "network:offline-status-changed", true);
|
||||||
Svc.Observer.addObserver(this, "private-browsing", true);
|
Svc.Observer.addObserver(this, "private-browsing", true);
|
||||||
Svc.Observer.addObserver(this, "quit-application", true);
|
Svc.Observer.addObserver(this, "quit-application", true);
|
||||||
|
Svc.Observer.addObserver(this, "weave:service:sync:finish", true);
|
||||||
|
Svc.Observer.addObserver(this, "weave:service:sync:error", true);
|
||||||
FaultTolerance.Service; // initialize FT service
|
FaultTolerance.Service; // initialize FT service
|
||||||
|
|
||||||
if (!this.enabled)
|
if (!this.enabled)
|
||||||
|
@ -334,7 +339,7 @@ WeaveSvc.prototype = {
|
||||||
if (Svc.Prefs.get("autoconnect") && this.username) {
|
if (Svc.Prefs.get("autoconnect") && this.username) {
|
||||||
try {
|
try {
|
||||||
if (this.login())
|
if (this.login())
|
||||||
this.sync(true);
|
this.syncOnIdle();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -423,23 +428,35 @@ WeaveSvc.prototype = {
|
||||||
case "enabled":
|
case "enabled":
|
||||||
case "schedule":
|
case "schedule":
|
||||||
// Potentially we'll want to reschedule syncs
|
// Potentially we'll want to reschedule syncs
|
||||||
this._checkSync();
|
this._checkSyncStatus();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "network:offline-status-changed":
|
case "network:offline-status-changed":
|
||||||
// Whether online or offline, we'll reschedule syncs
|
// Whether online or offline, we'll reschedule syncs
|
||||||
this._log.debug("Network offline status change: " + data);
|
this._log.debug("Network offline status change: " + data);
|
||||||
this._checkSync();
|
this._checkSyncStatus();
|
||||||
break;
|
break;
|
||||||
case "private-browsing":
|
case "private-browsing":
|
||||||
// Entering or exiting private browsing? Reschedule syncs
|
// Entering or exiting private browsing? Reschedule syncs
|
||||||
this._log.debug("Private browsing change: " + data);
|
this._log.debug("Private browsing change: " + data);
|
||||||
this._checkSync();
|
this._checkSyncStatus();
|
||||||
break;
|
break;
|
||||||
case "quit-application":
|
case "quit-application":
|
||||||
this._onQuitApplication();
|
this._onQuitApplication();
|
||||||
break;
|
break;
|
||||||
|
case "weave:service:sync:error":
|
||||||
|
this._handleSyncError();
|
||||||
|
break;
|
||||||
|
case "weave:service:sync:finish":
|
||||||
|
this._scheduleNextSync();
|
||||||
|
this._serverErrors = 0;
|
||||||
|
break;
|
||||||
|
case "idle":
|
||||||
|
this._log.debug("idle time hit, trying to sync");
|
||||||
|
Svc.Idle.removeIdleObserver(this, IDLE_TIME);
|
||||||
|
this.sync(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -620,7 +637,7 @@ WeaveSvc.prototype = {
|
||||||
|
|
||||||
// Try starting the sync timer now that we're logged in
|
// Try starting the sync timer now that we're logged in
|
||||||
this._loggedIn = true;
|
this._loggedIn = true;
|
||||||
this._checkSync();
|
this._checkSyncStatus();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})))(),
|
})))(),
|
||||||
|
@ -633,7 +650,7 @@ WeaveSvc.prototype = {
|
||||||
ID.get('WeaveCryptoID').setTempPassword(null); // and passphrase
|
ID.get('WeaveCryptoID').setTempPassword(null); // and passphrase
|
||||||
|
|
||||||
// Cancel the sync timer now that we're logged out
|
// Cancel the sync timer now that we're logged out
|
||||||
this._checkSync();
|
this._checkSyncStatus();
|
||||||
|
|
||||||
Svc.Observer.notifyObservers(null, "weave:service:logout:finish", "");
|
Svc.Observer.notifyObservers(null, "weave:service:logout:finish", "");
|
||||||
},
|
},
|
||||||
|
@ -816,8 +833,7 @@ WeaveSvc.prototype = {
|
||||||
_syncThresh: {},
|
_syncThresh: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a sync should run. If so, schedule a repeating sync;
|
* Determine if a sync should run.
|
||||||
* otherwise, cancel future syncs and return a reason.
|
|
||||||
*
|
*
|
||||||
* @return Reason for not syncing; not-truthy if sync should run
|
* @return Reason for not syncing; not-truthy if sync should run
|
||||||
*/
|
*/
|
||||||
|
@ -835,31 +851,114 @@ WeaveSvc.prototype = {
|
||||||
else if (Svc.Prefs.get("schedule", 0) != 1)
|
else if (Svc.Prefs.get("schedule", 0) != 1)
|
||||||
reason = kSyncNotScheduled;
|
reason = kSyncNotScheduled;
|
||||||
|
|
||||||
// A truthy reason means we shouldn't continue to sync
|
return reason;
|
||||||
if (reason) {
|
},
|
||||||
// Cancel any future syncs
|
|
||||||
|
/**
|
||||||
|
* Check if we should be syncing and schedule the next sync, if it's not scheduled
|
||||||
|
*/
|
||||||
|
_checkSyncStatus: function WeaveSvc__checkSyncStatus() {
|
||||||
|
// Should we be syncing now, if not, cancel any sync timers and return
|
||||||
|
if (this._checkSync()) {
|
||||||
if (this._syncTimer) {
|
if (this._syncTimer) {
|
||||||
this._syncTimer.cancel();
|
this._syncTimer.cancel();
|
||||||
this._syncTimer = null;
|
this._syncTimer = null;
|
||||||
}
|
}
|
||||||
this._log.config("Weave scheduler disabled: " + reason);
|
|
||||||
}
|
try {
|
||||||
// We're good to sync, so schedule a repeating sync if we haven't yet
|
Svc.Idle.removeIdleObserver(this, IDLE_TIME);
|
||||||
else if (!this._syncTimer) {
|
} catch(e) {} // this throws if there isn't an observer, but that's fine
|
||||||
this._syncTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
||||||
let listener = new Utils.EventListener(Utils.bind2(this,
|
return;
|
||||||
function WeaveSvc__checkSyncCallback(timer) {
|
|
||||||
if (this.locked)
|
|
||||||
this._log.debug("Skipping scheduled sync: already locked for sync");
|
|
||||||
else
|
|
||||||
this.sync(false);
|
|
||||||
}));
|
|
||||||
this._syncTimer.initWithCallback(listener, SCHEDULED_SYNC_INTERVAL,
|
|
||||||
Ci.nsITimer.TYPE_REPEATING_SLACK);
|
|
||||||
this._log.config("Weave scheduler enabled");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return reason;
|
// otherwise, schedule the sync
|
||||||
|
this._scheduleNextSync();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call sync() on an idle timer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
syncOnIdle: function WeaveSvc_syncOnIdle() {
|
||||||
|
this._log.debug("Idle timer created for sync, will sync after " +
|
||||||
|
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 = SCHEDULED_SYNC_INTERVAL;
|
||||||
|
|
||||||
|
// if there's an existing timer, cancel it and restart
|
||||||
|
if (this._syncTimer)
|
||||||
|
this._syncTimer.cancel();
|
||||||
|
else
|
||||||
|
this._syncTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
|
|
||||||
|
let listener = new Utils.EventListener(Utils.bind2(this,
|
||||||
|
function WeaveSvc__scheduleNextSyncCallback(timer) {
|
||||||
|
this._syncTimer = null;
|
||||||
|
this.syncOnIdle();
|
||||||
|
}));
|
||||||
|
this._syncTimer.initWithCallback(listener, interval,
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||||
|
this._log.debug("Next sync call in: " + this._syncTimer.delay / 1000 + " seconds.")
|
||||||
|
},
|
||||||
|
|
||||||
|
_serverErrors: 0,
|
||||||
|
/**
|
||||||
|
* Deal with sync errors appropriately
|
||||||
|
*/
|
||||||
|
_handleSyncError: function WeaveSvc__handleSyncError() {
|
||||||
|
let shouldBackoff = false;
|
||||||
|
|
||||||
|
let err = Weave.Service.detailedStatus.sync;
|
||||||
|
// we'll assume the server is just borked a little for these
|
||||||
|
switch (err) {
|
||||||
|
case METARECORD_DOWNLOAD_FAIL:
|
||||||
|
case KEYS_DOWNLOAD_FAIL:
|
||||||
|
case KEYS_UPLOAD_FAIL:
|
||||||
|
shouldBackoff = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specifcally handle 500, 502, 503, 504 errors
|
||||||
|
// xxxmpc: what else should be in this list?
|
||||||
|
// this is sort of pseudocode, need a way to get at the
|
||||||
|
if (!shouldBackoff &&
|
||||||
|
Utils.checkStatus(Records.lastResource.lastChannel.responseStatus, null, [500,[502,504]])) {
|
||||||
|
shouldBackoff = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is a client error, do the next sync as normal and return
|
||||||
|
if (!shouldBackoff) {
|
||||||
|
this._scheduleNextSync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok, something failed connecting to the server, rev the counter
|
||||||
|
this._serverErrors++;
|
||||||
|
|
||||||
|
// do nothing on the first failure, if we fail again we'll back off
|
||||||
|
if (this._serverErrors < 2) {
|
||||||
|
this._scheduleNextSync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 30-60 minute backoff interval, increasing each time
|
||||||
|
const MINIMUM_BACKOFF_INTERVAL = 15 * 60 * 1000; // 15 minutes * >= 2
|
||||||
|
const MAXIMUM_BACKOFF_INTERVAL = 8 * 60 * 60 * 1000; // 8 hours
|
||||||
|
let backoffInterval = this._serverErrors *
|
||||||
|
(Math.floor(Math.random() * MINIMUM_BACKOFF_INTERVAL) +
|
||||||
|
MINIMUM_BACKOFF_INTERVAL);
|
||||||
|
backoffInterval = Math.min(backoffInterval, MAXIMUM_BACKOFF_INTERVAL);
|
||||||
|
this._scheduleNextSync(backoffInterval);
|
||||||
|
|
||||||
|
let d = new Date(Date.now() + backoffInterval);
|
||||||
|
this._log.config("Starting backoff, next sync at:" + d.toString());
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -871,12 +970,6 @@ WeaveSvc.prototype = {
|
||||||
sync: function WeaveSvc_sync(fullSync)
|
sync: function WeaveSvc_sync(fullSync)
|
||||||
this._catch(this._lock(this._notify("sync", "", function() {
|
this._catch(this._lock(this._notify("sync", "", function() {
|
||||||
|
|
||||||
// Skip this incremental sync if the user has been active recently
|
|
||||||
if (!fullSync && Svc.Idle.idleTime < 30000) {
|
|
||||||
this._log.debug("Skipped sync because the user was active.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullSync = true; // not doing thresholds yet
|
fullSync = true; // not doing thresholds yet
|
||||||
|
|
||||||
// Use thresholds to determine what to sync only if it's not a full sync
|
// Use thresholds to determine what to sync only if it's not a full sync
|
||||||
|
|
Загрузка…
Ссылка в новой задаче