diff --git a/synapse/storage/databases/main/lock.py b/synapse/storage/databases/main/lock.py index bedacaf0d745..abd3f7a7a496 100644 --- a/synapse/storage/databases/main/lock.py +++ b/synapse/storage/databases/main/lock.py @@ -26,6 +26,7 @@ LoggingTransaction, ) from synapse.util import Clock +from synapse.util.async_helpers import Linearizer from synapse.util.stringutils import random_string if TYPE_CHECKING: @@ -84,6 +85,8 @@ def __init__( self._on_shutdown, ) + self.limiter = Linearizer("database_lock_linearizer") + @wrap_as_background_process("LockStore._on_shutdown") async def _on_shutdown(self) -> None: """Called when the server is shutting down""" @@ -103,6 +106,16 @@ async def try_acquire_lock(self, lock_name: str, lock_key: str) -> Optional["Loc context manager if the lock is successfully acquired, which *must* be used (otherwise the lock will leak). """ + async with self.limiter.queue((lock_name, lock_key)): + return await self._try_acquire_lock(lock_name, lock_key) + + async def _try_acquire_lock( + self, lock_name: str, lock_key: str + ) -> Optional["Lock"]: + """Try to acquire a lock for the given name/key. Will return an async + context manager if the lock is successfully acquired, which *must* be + used (otherwise the lock will leak). + """ # Check if this process has taken out a lock and if it's still valid. lock = self._live_tokens.get((lock_name, lock_key))