From 099334d50f70933acedea9f0e3f037ff562feae2 Mon Sep 17 00:00:00 2001 From: Sumner Evans Date: Sat, 21 May 2022 16:20:02 -0600 Subject: [PATCH] database/LockStore: use Linearizer for lock acquisition This fixes the "test_acquire_contention" test case added in the previous commit. Signed-off-by: Sumner Evans --- synapse/storage/databases/main/lock.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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))