diff --git a/lib/sync.js b/lib/sync.js index f1581cd329a..e4086a994c0 100644 --- a/lib/sync.js +++ b/lib/sync.js @@ -545,13 +545,28 @@ SyncApi.prototype._sync = function(syncOptions) { console.error("/sync error %s", err); console.error(err); - debuglog("Starting keep-alive"); - self._syncConnectionLost = true; - self._startKeepAlives().done(function() { + if (!self._syncConnectionLost) { + // This is the first failure, which may be spurious. To avoid unnecessary + // connection error warnings we simply retry the /sync immediately. Only + // if *that* one fails too do we say the connection has been lost. + // Examples of when this may happen are: + // - Restarting backend servers. (In an HA world backends may be + // restarted all the time, and its easiest just to make the + // client retry). + // - Intermediate proxies restarting. + // - Device network changes. + // Should we emit a state like "MAYBE_CONNETION_LOST"? + self._syncConnectionLost = true; self._sync(syncOptions); - }); - self._currentSyncRequest = null; - self._updateSyncState("ERROR", { error: err }); + } else { + debuglog("Starting keep-alive"); + self._syncConnectionLost = true; + self._startKeepAlives().done(function() { + self._sync(syncOptions); + }); + self._currentSyncRequest = null; + self._updateSyncState("ERROR", { error: err }); + } }); }; diff --git a/spec/unit/matrix-client.spec.js b/spec/unit/matrix-client.spec.js index 738c3255838..8e2fe69acdc 100644 --- a/spec/unit/matrix-client.spec.js +++ b/spec/unit/matrix-client.spec.js @@ -332,9 +332,13 @@ describe("MatrixClient", function() { httpLookups = []; httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(FILTER_RESPONSE); + // We fail twice since the SDK ignores the first error. httpLookups.push({ method: "GET", path: "/sync", error: { errcode: "NOPE_NOPE_NOPE" } }); + httpLookups.push({ + method: "GET", path: "/sync", error: { errcode: "NOPE_NOPE_NOPE2" } + }); httpLookups.push({ method: "GET", path: "/sync", data: SYNC_DATA }); @@ -355,9 +359,13 @@ describe("MatrixClient", function() { it("should transition SYNCING -> ERROR after a failed /sync", function(done) { var expectedStates = []; + // We fail twice since the SDK ignores the first error. httpLookups.push({ method: "GET", path: "/sync", error: { errcode: "NONONONONO" } }); + httpLookups.push({ + method: "GET", path: "/sync", error: { errcode: "NONONONONO2" } + }); expectedStates.push(["PREPARED", null]); expectedStates.push(["SYNCING", "PREPARED"]); @@ -396,6 +404,10 @@ describe("MatrixClient", function() { it("should transition ERROR -> ERROR if multiple /sync fails", function(done) { var expectedStates = []; + // We fail twice since the SDK ignores the first error. + httpLookups.push({ + method: "GET", path: "/sync", error: { errcode: "NONONONONO" } + }); httpLookups.push({ method: "GET", path: "/sync", error: { errcode: "NONONONONO" } });