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:
reivilibre 2022-02-22 13:29:04 +00:00 committed by GitHub
parent 6a1bad511d
commit 235d2916ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 136 additions and 4 deletions

View file

@ -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
)