You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
Don't send key requests until after sync processing is finished
Key requests wait for a short time (500ms) before being sent as an attempt to wait for the key to arrive before sending a request for it, but client startup takes way longer than this so this would still result in key requests being sent for keys that we'd fetched but were still waiting to be read out of the sync response and put into the database.
This commit is contained in:
@@ -313,6 +313,10 @@ describe("Crypto", function() {
|
|||||||
// make a room key request, and record the transaction ID for the
|
// make a room key request, and record the transaction ID for the
|
||||||
// sendToDevice call
|
// sendToDevice call
|
||||||
await aliceClient.cancelAndResendEventRoomKeyRequest(event);
|
await aliceClient.cancelAndResendEventRoomKeyRequest(event);
|
||||||
|
// key requests get queued until the sync has finished, but we don't
|
||||||
|
// let the client set up enough for that to happen, so gut-wrench a bit
|
||||||
|
// to force it to send now.
|
||||||
|
aliceClient._crypto._outgoingRoomKeyRequestManager.sendQueuedRequests();
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
expect(aliceClient.sendToDevice).toBeCalledTimes(1);
|
expect(aliceClient.sendToDevice).toBeCalledTimes(1);
|
||||||
|
|||||||
@@ -97,10 +97,6 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
*/
|
*/
|
||||||
start() {
|
start() {
|
||||||
this._clientRunning = true;
|
this._clientRunning = true;
|
||||||
|
|
||||||
// set the timer going, to handle any requests which didn't get sent
|
|
||||||
// on the previous run of the client.
|
|
||||||
this._startTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,7 +109,14 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send off a room key request, if we haven't already done so.
|
* Send any requests that have been queued
|
||||||
|
*/
|
||||||
|
sendQueuedRequests() {
|
||||||
|
this._startTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue up a room key request, if we haven't already queued or sent one.
|
||||||
*
|
*
|
||||||
* The `requestBody` is compared (with a deep-equality check) against
|
* The `requestBody` is compared (with a deep-equality check) against
|
||||||
* previous queued or sent requests and if it matches, no change is made.
|
* previous queued or sent requests and if it matches, no change is made.
|
||||||
@@ -129,7 +132,7 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
* pending list (or we have established that a similar request already
|
* pending list (or we have established that a similar request already
|
||||||
* exists)
|
* exists)
|
||||||
*/
|
*/
|
||||||
async sendRoomKeyRequest(requestBody, recipients, resend=false) {
|
async queueRoomKeyRequest(requestBody, recipients, resend=false) {
|
||||||
const req = await this._cryptoStore.getOutgoingRoomKeyRequest(
|
const req = await this._cryptoStore.getOutgoingRoomKeyRequest(
|
||||||
requestBody,
|
requestBody,
|
||||||
);
|
);
|
||||||
@@ -184,7 +187,7 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
// in state ROOM_KEY_REQUEST_STATES.SENT, so we must have
|
// in state ROOM_KEY_REQUEST_STATES.SENT, so we must have
|
||||||
// raced with another tab to mark the request cancelled.
|
// raced with another tab to mark the request cancelled.
|
||||||
// Try again, to make sure the request is resent.
|
// Try again, to make sure the request is resent.
|
||||||
return await this.sendRoomKeyRequest(
|
return await this.queueRoomKeyRequest(
|
||||||
requestBody, recipients, resend,
|
requestBody, recipients, resend,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -220,9 +223,6 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
throw new Error('unhandled state: ' + req.state);
|
throw new Error('unhandled state: ' + req.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// some of the branches require the timer to be started. Just start it
|
|
||||||
// all the time, because it doesn't hurt to start it.
|
|
||||||
this._startTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -302,7 +302,6 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
"Error sending room key request cancellation;"
|
"Error sending room key request cancellation;"
|
||||||
+ " will retry later.", e,
|
+ " will retry later.", e,
|
||||||
);
|
);
|
||||||
this._startTimer();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -332,14 +331,14 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
* This is intended for situations where something substantial has changed, and we
|
* This is intended for situations where something substantial has changed, and we
|
||||||
* don't really expect the other end to even care about the cancellation.
|
* don't really expect the other end to even care about the cancellation.
|
||||||
* For example, after initialization or self-verification.
|
* For example, after initialization or self-verification.
|
||||||
* @return {Promise} An array of `sendRoomKeyRequest` outputs.
|
* @return {Promise} An array of `queueRoomKeyRequest` outputs.
|
||||||
*/
|
*/
|
||||||
async cancelAndResendAllOutgoingRequests() {
|
async cancelAndResendAllOutgoingRequests() {
|
||||||
const outgoings = await this._cryptoStore.getAllOutgoingRoomKeyRequestsByState(
|
const outgoings = await this._cryptoStore.getAllOutgoingRoomKeyRequestsByState(
|
||||||
ROOM_KEY_REQUEST_STATES.SENT,
|
ROOM_KEY_REQUEST_STATES.SENT,
|
||||||
);
|
);
|
||||||
return Promise.all(outgoings.map(({ requestBody, recipients }) =>
|
return Promise.all(outgoings.map(({ requestBody, recipients }) =>
|
||||||
this.sendRoomKeyRequest(requestBody, recipients, true)));
|
this.queueRoomKeyRequest(requestBody, recipients, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the background timer to send queued requests, if the timer isn't
|
// start the background timer to send queued requests, if the timer isn't
|
||||||
@@ -381,15 +380,12 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log("Looking for queued outgoing room key requests");
|
|
||||||
|
|
||||||
return this._cryptoStore.getOutgoingRoomKeyRequestByState([
|
return this._cryptoStore.getOutgoingRoomKeyRequestByState([
|
||||||
ROOM_KEY_REQUEST_STATES.CANCELLATION_PENDING,
|
ROOM_KEY_REQUEST_STATES.CANCELLATION_PENDING,
|
||||||
ROOM_KEY_REQUEST_STATES.CANCELLATION_PENDING_AND_WILL_RESEND,
|
ROOM_KEY_REQUEST_STATES.CANCELLATION_PENDING_AND_WILL_RESEND,
|
||||||
ROOM_KEY_REQUEST_STATES.UNSENT,
|
ROOM_KEY_REQUEST_STATES.UNSENT,
|
||||||
]).then((req) => {
|
]).then((req) => {
|
||||||
if (!req) {
|
if (!req) {
|
||||||
logger.log("No more outgoing room key requests");
|
|
||||||
this._sendOutgoingRoomKeyRequestsTimer = null;
|
this._sendOutgoingRoomKeyRequestsTimer = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -413,7 +409,6 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
logger.error("Error sending room key request; will retry later.", e);
|
logger.error("Error sending room key request; will retry later.", e);
|
||||||
this._sendOutgoingRoomKeyRequestsTimer = null;
|
this._sendOutgoingRoomKeyRequestsTimer = null;
|
||||||
this._startTimer();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,6 +223,11 @@ export function Crypto(baseApis, sessionStore, userId, deviceId,
|
|||||||
this._toDeviceVerificationRequests = new ToDeviceRequests();
|
this._toDeviceVerificationRequests = new ToDeviceRequests();
|
||||||
this._inRoomVerificationRequests = new InRoomRequests();
|
this._inRoomVerificationRequests = new InRoomRequests();
|
||||||
|
|
||||||
|
// This flag will be unset whilst the client processes a sync response
|
||||||
|
// so that we don't start requesting keys until we've actually finished
|
||||||
|
// processing the response.
|
||||||
|
this._sendKeyRequestsImmediately = false;
|
||||||
|
|
||||||
const cryptoCallbacks = this._baseApis._cryptoCallbacks || {};
|
const cryptoCallbacks = this._baseApis._cryptoCallbacks || {};
|
||||||
const cacheCallbacks = createCryptoStoreCacheCallbacks(cryptoStore);
|
const cacheCallbacks = createCryptoStoreCacheCallbacks(cryptoStore);
|
||||||
|
|
||||||
@@ -2875,7 +2880,7 @@ Crypto.prototype.handleDeviceListChanges = async function(syncData, syncDeviceLi
|
|||||||
* @return {Promise} a promise that resolves when the key request is queued
|
* @return {Promise} a promise that resolves when the key request is queued
|
||||||
*/
|
*/
|
||||||
Crypto.prototype.requestRoomKey = function(requestBody, recipients, resend=false) {
|
Crypto.prototype.requestRoomKey = function(requestBody, recipients, resend=false) {
|
||||||
return this._outgoingRoomKeyRequestManager.sendRoomKeyRequest(
|
return this._outgoingRoomKeyRequestManager.queueRoomKeyRequest(
|
||||||
requestBody, recipients, resend,
|
requestBody, recipients, resend,
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
// this normally means we couldn't talk to the store
|
// this normally means we couldn't talk to the store
|
||||||
@@ -2883,6 +2888,9 @@ Crypto.prototype.requestRoomKey = function(requestBody, recipients, resend=false
|
|||||||
'Error requesting key for event', e,
|
'Error requesting key for event', e,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
if (this._sendKeyRequestsImmediately) {
|
||||||
|
this._outgoingRoomKeyRequestManager.sendQueuedRequests();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2942,6 +2950,8 @@ Crypto.prototype.onSyncWillProcess = async function(syncData) {
|
|||||||
this._deviceList.startTrackingDeviceList(this._userId);
|
this._deviceList.startTrackingDeviceList(this._userId);
|
||||||
this._roomDeviceTrackingState = {};
|
this._roomDeviceTrackingState = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._sendKeyRequestsImmediately = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2973,6 +2983,14 @@ Crypto.prototype.onSyncCompleted = async function(syncData) {
|
|||||||
if (!syncData.catchingUp) {
|
if (!syncData.catchingUp) {
|
||||||
_maybeUploadOneTimeKeys(this);
|
_maybeUploadOneTimeKeys(this);
|
||||||
this._processReceivedRoomKeyRequests();
|
this._processReceivedRoomKeyRequests();
|
||||||
|
|
||||||
|
// likewise don't start requesting keys until we've caught up
|
||||||
|
// on to_device messages, otherwise we'll request keys that we're
|
||||||
|
// just about to get.
|
||||||
|
this._outgoingRoomKeyRequestManager.sendQueuedRequests();
|
||||||
|
|
||||||
|
// Sync has finished so send key requests straight away.
|
||||||
|
this._sendKeyRequestsImmediately = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user