From 4a1e84f090b09196a209964a60bed54a0083103b Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 29 Sep 2024 12:28:47 +0100 Subject: [PATCH] lsp: Create a placeholder for a client at the given scope When `manager.get_client` is called many times in quick succession (such as on server restart with N files open) this can fool the `SphinxManager` into creating multiple client instances for a given configuration scope. By storing a ``None`` at the relevant scope we allow the SphinxManager to detect that the scope has already been handled, preventing the spawning of duplicated client instances. This should, finally, fix the flaky test issue (#859) --- .../server/features/sphinx_manager/manager.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py b/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py index c0246288..7cee14f1 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py +++ b/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py @@ -238,8 +238,18 @@ async def get_client(self, uri: Uri) -> SphinxClient | None: partial(self._create_or_replace_client, uri), scope=uri, ) - # The first few callers in a given scope will miss out, but that shouldn't matter - # too much + + # It's possible for this code path to be hit multiple times in quick + # succession e.g. on a fresh server start with N .rst files already open, + # creating the opportunity to accidentally spawn N duplicated clients! + # + # To prevent this, store a `None` at this scope, all being well it will be + # replaced with the actual client instance when the + # `_create_or_replace_client` callback runs. + self.clients[scope] = None + + # The first few callers in a given scope will miss out, but that shouldn't + # matter too much return None if (client := self.clients[scope]) is None: