mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-09-21 07:24:34 -04:00
Fix slow performance of /logout
in some cases where refresh tokens are in use. The slowness existed since the initial implementation of refresh tokens. (#12056)
This commit is contained in:
parent
6a1bad511d
commit
235d2916ce
4 changed files with 136 additions and 4 deletions
|
@ -1681,7 +1681,8 @@ class RegistrationWorkerStore(CacheInvalidationWorkerStore):
|
|||
user_id=row[1],
|
||||
device_id=row[2],
|
||||
next_token_id=row[3],
|
||||
has_next_refresh_token_been_refreshed=row[4],
|
||||
# SQLite returns 0 or 1 for false/true, so convert to a bool.
|
||||
has_next_refresh_token_been_refreshed=bool(row[4]),
|
||||
# This column is nullable, ensure it's a boolean
|
||||
has_next_access_token_been_used=(row[5] or False),
|
||||
expiry_ts=row[6],
|
||||
|
@ -1697,12 +1698,15 @@ class RegistrationWorkerStore(CacheInvalidationWorkerStore):
|
|||
Set the successor of a refresh token, removing the existing successor
|
||||
if any.
|
||||
|
||||
This also deletes the predecessor refresh and access tokens,
|
||||
since they cannot be valid anymore.
|
||||
|
||||
Args:
|
||||
token_id: ID of the refresh token to update.
|
||||
next_token_id: ID of its successor.
|
||||
"""
|
||||
|
||||
def _replace_refresh_token_txn(txn) -> None:
|
||||
def _replace_refresh_token_txn(txn: LoggingTransaction) -> None:
|
||||
# First check if there was an existing refresh token
|
||||
old_next_token_id = self.db_pool.simple_select_one_onecol_txn(
|
||||
txn,
|
||||
|
@ -1728,6 +1732,16 @@ class RegistrationWorkerStore(CacheInvalidationWorkerStore):
|
|||
{"id": old_next_token_id},
|
||||
)
|
||||
|
||||
# Delete the previous refresh token, since we only want to keep the
|
||||
# last 2 refresh tokens in the database.
|
||||
# (The predecessor of the latest refresh token is still useful in
|
||||
# case the refresh was interrupted and the client re-uses the old
|
||||
# one.)
|
||||
# This cascades to delete the associated access token.
|
||||
self.db_pool.simple_delete_txn(
|
||||
txn, "refresh_tokens", {"next_token_id": token_id}
|
||||
)
|
||||
|
||||
await self.db_pool.runInteraction(
|
||||
"replace_refresh_token", _replace_refresh_token_txn
|
||||
)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright 2022 The Matrix.org Foundation C.I.C
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
-- next_token_id is a foreign key reference, so previously required a table scan
|
||||
-- when a row in the referenced table was deleted.
|
||||
-- As it was self-referential and cascaded deletes, this led to O(t*n) time to
|
||||
-- delete a row, where t: number of rows in the table and n: number of rows in
|
||||
-- the ancestral 'chain' of access tokens.
|
||||
--
|
||||
-- This index is partial since we only require it for rows which reference
|
||||
-- another.
|
||||
-- Performance was tested to be the same regardless of whether the index was
|
||||
-- full or partial, but a partial index can be smaller.
|
||||
CREATE INDEX refresh_tokens_next_token_id
|
||||
ON refresh_tokens(next_token_id)
|
||||
WHERE next_token_id IS NOT NULL;
|
Loading…
Add table
Add a link
Reference in a new issue