1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-28 05:03:59 +03:00

Merge branch 'develop' into kegan/indexeddb

This commit is contained in:
Kegan Dougal
2017-02-17 09:41:16 +00:00
2 changed files with 67 additions and 16 deletions

View File

@@ -3042,21 +3042,26 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
/** /**
* Fires whenever the SDK's syncing state is updated. The state can be one of: * Fires whenever the SDK's syncing state is updated. The state can be one of:
* <ul> * <ul>
* <li>PREPARED : The client has synced with the server at least once and is *
* <li>PREPARED: The client has synced with the server at least once and is
* ready for methods to be called on it. This will be immediately followed by * ready for methods to be called on it. This will be immediately followed by
* a state of SYNCING. <i>This is the equivalent of "syncComplete" in the * a state of SYNCING. <i>This is the equivalent of "syncComplete" in the
* previous API.</i></li> * previous API.</i></li>
*
* <li>SYNCING : The client is currently polling for new events from the server. * <li>SYNCING : The client is currently polling for new events from the server.
* This will be called <i>after</i> processing latest events from a sync.</li> * This will be called <i>after</i> processing latest events from a sync.</li>
*
* <li>ERROR : The client has had a problem syncing with the server. If this is * <li>ERROR : The client has had a problem syncing with the server. If this is
* called <i>before</i> PREPARED then there was a problem performing the initial * called <i>before</i> PREPARED then there was a problem performing the initial
* sync. If this is called <i>after</i> PREPARED then there was a problem polling * sync. If this is called <i>after</i> PREPARED then there was a problem polling
* the server for updates. This may be called multiple times even if the state is * the server for updates. This may be called multiple times even if the state is
* already ERROR. <i>This is the equivalent of "syncError" in the previous * already ERROR. <i>This is the equivalent of "syncError" in the previous
* API.</i></li> * API.</i></li>
* <li>RECONNECTING: The sync connedtion has dropped, but not in a way that should *
* be considered erroneous. * <li>RECONNECTING: The sync connection has dropped, but not (yet) in a way that
* should be considered erroneous.
* </li> * </li>
*
* <li>STOPPED: The client has stopped syncing with server due to stopClient * <li>STOPPED: The client has stopped syncing with server due to stopClient
* being called. * being called.
* </li> * </li>
@@ -3066,32 +3071,46 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* +---->STOPPED * +---->STOPPED
* | * |
* +----->PREPARED -------> SYNCING <--+ * +----->PREPARED -------> SYNCING <--+
* | ^ ^ | * | ^ | ^ |
* | | | | * | | | | |
* | | V | * | | V | |
* null ------+ | +-RECONNECTING<-+ | * null ------+ | +--------RECONNECTING |
* | | V | * | | V |
* +------->ERROR ---------------------+ * +------->ERROR ---------------------+
* *
* NB: 'null' will never be emitted by this event. * NB: 'null' will never be emitted by this event.
*
* </pre> * </pre>
* Transitions: * Transitions:
* <ul> * <ul>
*
* <li><code>null -> PREPARED</code> : Occurs when the initial sync is completed * <li><code>null -> PREPARED</code> : Occurs when the initial sync is completed
* first time. This involves setting up filters and obtaining push rules. * first time. This involves setting up filters and obtaining push rules.
*
* <li><code>null -> ERROR</code> : Occurs when the initial sync failed first time. * <li><code>null -> ERROR</code> : Occurs when the initial sync failed first time.
*
* <li><code>ERROR -> PREPARED</code> : Occurs when the initial sync succeeds * <li><code>ERROR -> PREPARED</code> : Occurs when the initial sync succeeds
* after previously failing. * after previously failing.
*
* <li><code>PREPARED -> SYNCING</code> : Occurs immediately after transitioning * <li><code>PREPARED -> SYNCING</code> : Occurs immediately after transitioning
* to PREPARED. Starts listening for live updates rather than catching up. * to PREPARED. Starts listening for live updates rather than catching up.
* <li><code>SYNCING -> ERROR</code> : Occurs the first time a client cannot perform a *
* live update. * <li><code>SYNCING -> RECONNECTING</code> : Occurs when the live update fails.
*
* <li><code>RECONNECTING -> RECONNECTING</code> : Can occur if the update calls
* continue to fail, but the keepalive calls (to /versions) succeed.
*
* <li><code>RECONNECTING -> ERROR</code> : Occurs when the keepalive call also fails
*
* <li><code>ERROR -> SYNCING</code> : Occurs when the client has performed a * <li><code>ERROR -> SYNCING</code> : Occurs when the client has performed a
* live update after having previously failed. * live update after having previously failed.
* <li><code>ERROR -> ERROR</code> : Occurs when the client has failed to sync *
* <li><code>ERROR -> ERROR</code> : Occurs when the client has failed to keepalive
* for a second time or more.</li> * for a second time or more.</li>
*
* <li><code>SYNCING -> SYNCING</code> : Occurs when the client has performed a live * <li><code>SYNCING -> SYNCING</code> : Occurs when the client has performed a live
* update. This is called <i>after</i> processing.</li> * update. This is called <i>after</i> processing.</li>
*
* <li><code>* -> STOPPED</code> : Occurs once the client has stopped syncing or * <li><code>* -> STOPPED</code> : Occurs once the client has stopped syncing or
* trying to sync after stopClient has been called.</li> * trying to sync after stopClient has been called.</li>
* </ul> * </ul>
@@ -3117,6 +3136,9 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* will become the 'since' token for the next call to /sync. Only present if * will become the 'since' token for the next call to /sync. Only present if
* <code>state=PREPARED</code> or <code>state=SYNCING</code>. * <code>state=PREPARED</code> or <code>state=SYNCING</code>.
* *
* @param {boolean} data.catchingUp True if we are working our way through a
* backlog of events after connecting. Only present if <code>state=SYNCING</code>.
*
* @example * @example
* matrixClient.on("sync", function(state, prevState, data) { * matrixClient.on("sync", function(state, prevState, data) {
* switch (state) { * switch (state) {

View File

@@ -77,6 +77,7 @@ function SyncApi(client, opts) {
this._peekRoomId = null; this._peekRoomId = null;
this._currentSyncRequest = null; this._currentSyncRequest = null;
this._syncState = null; this._syncState = null;
this._catchingUp = false;
this._running = false; this._running = false;
this._keepAliveTimer = null; this._keepAliveTimer = null;
this._connectionReturnedDefer = null; this._connectionReturnedDefer = null;
@@ -487,9 +488,30 @@ SyncApi.prototype._sync = function(syncOptions) {
const syncToken = client.store.getSyncToken(); const syncToken = client.store.getSyncToken();
let pollTimeout = this.opts.pollTimeout;
if (this.getSyncState() !== 'SYNCING' || this._catchingUp) {
// unless we are happily syncing already, we want the server to return
// as quickly as possible, even if there are no events queued. This
// serves two purposes:
//
// * When the connection dies, we want to know asap when it comes back,
// so that we can hide the error from the user. (We don't want to
// have to wait for an event or a timeout).
//
// * We want to know if the server has any to_device messages queued up
// for us. We do that by calling it with a zero timeout until it
// doesn't give us any more to_device messages.
this._catchingUp = true;
pollTimeout = 0;
}
// normal timeout= plus buffer time
const clientSideTimeoutMs = pollTimeout + BUFFER_PERIOD_MS;
const qps = { const qps = {
filter: filterId, filter: filterId,
timeout: this.opts.pollTimeout, timeout: pollTimeout,
}; };
if (syncToken) { if (syncToken) {
@@ -527,9 +549,6 @@ SyncApi.prototype._sync = function(syncOptions) {
} }
} }
// normal timeout= plus buffer time
const clientSideTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS;
if (!isCachedResponse) { if (!isCachedResponse) {
debuglog('Starting sync since=' + syncToken); debuglog('Starting sync since=' + syncToken);
this._currentSyncRequest = client._http.authedRequest( this._currentSyncRequest = client._http.authedRequest(
@@ -564,6 +583,7 @@ SyncApi.prototype._sync = function(syncOptions) {
const syncEventData = { const syncEventData = {
oldSyncToken: syncToken, oldSyncToken: syncToken,
nextSyncToken: data.next_batch, nextSyncToken: data.next_batch,
catchingUp: self._catchingUp,
}; };
if (!syncOptions.hasSyncedBefore) { if (!syncOptions.hasSyncedBefore) {
@@ -691,7 +711,9 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
} }
// handle to-device events // handle to-device events
if (data.to_device && utils.isArray(data.to_device.events)) { if (data.to_device && utils.isArray(data.to_device.events) &&
data.to_device.events.length > 0
) {
data.to_device.events data.to_device.events
.map(client.getEventMapper()) .map(client.getEventMapper())
.forEach( .forEach(
@@ -712,6 +734,9 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
client.emit("toDeviceEvent", toDeviceEvent); client.emit("toDeviceEvent", toDeviceEvent);
}, },
); );
} else {
// no more to-device events: we can stop polling with a short timeout.
this._catchingUp = false;
} }
// the returned json structure is a bit crap, so make it into a // the returned json structure is a bit crap, so make it into a
@@ -917,7 +942,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
* @param {number} delay How long to delay until the first poll. * @param {number} delay How long to delay until the first poll.
* defaults to a short, randomised interval (to prevent * defaults to a short, randomised interval (to prevent
* tightlooping if /versions succeeds but /sync etc. fail). * tightlooping if /versions succeeds but /sync etc. fail).
* @return {promise} * @return {promise} which resolves once the connection returns
*/ */
SyncApi.prototype._startKeepAlives = function(delay) { SyncApi.prototype._startKeepAlives = function(delay) {
if (delay === undefined) { if (delay === undefined) {
@@ -943,7 +968,11 @@ SyncApi.prototype._startKeepAlives = function(delay) {
}; };
/** /**
* Make a dummy call to /_matrix/client/versions, to see if the HS is
* reachable.
* *
* On failure, schedules a call back to itself. On success, resolves
* this._connectionReturnedDefer.
*/ */
SyncApi.prototype._pokeKeepAlive = function() { SyncApi.prototype._pokeKeepAlive = function() {
const self = this; const self = this;