You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Poll /sync with a short timeout while catching up
On first connect, or after a disconnection, poll /sync with timeout=0 until we get no to_device messages back. This will allow us to figure out whether we have more to_device messages queued up for us on the server, which in turn will help us fix a bug with clearing out one-time-keys too quickly.
This commit is contained in:
@@ -3132,6 +3132,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) {
|
||||||
|
|||||||
43
src/sync.js
43
src/sync.js
@@ -73,6 +73,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;
|
||||||
@@ -483,9 +484,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) {
|
||||||
@@ -497,17 +519,6 @@ SyncApi.prototype._sync = function(syncOptions) {
|
|||||||
qps._cacheBuster = Date.now();
|
qps._cacheBuster = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getSyncState() == 'ERROR' || this.getSyncState() == 'RECONNECTING') {
|
|
||||||
// we think the connection is dead. If it comes back up, we won't know
|
|
||||||
// about it till /sync returns. If the timeout= is high, this could
|
|
||||||
// be a long time. Set it to 0 when doing retries so we don't have to wait
|
|
||||||
// for an event or a timeout before emiting the SYNCING event.
|
|
||||||
qps.timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// normal timeout= plus buffer time
|
|
||||||
const clientSideTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS;
|
|
||||||
|
|
||||||
debuglog('Starting sync since=' + syncToken);
|
debuglog('Starting sync since=' + syncToken);
|
||||||
this._currentSyncRequest = client._http.authedRequest(
|
this._currentSyncRequest = client._http.authedRequest(
|
||||||
undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs,
|
undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs,
|
||||||
@@ -533,6 +544,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) {
|
||||||
@@ -656,7 +668,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(
|
||||||
@@ -677,6 +691,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
|
||||||
|
|||||||
Reference in New Issue
Block a user