From a65bebcdaf9d15f7e6437242db95a27e2ae26d63 Mon Sep 17 00:00:00 2001 From: Maicon Berlofa Date: Mon, 6 Apr 2026 14:40:51 -0300 Subject: [PATCH] fix(server): add requests dependency and fix cache lock race condition Add requests>=2.31 to requirements.txt so tool packages that depend on it (github, http, notifications) work at runtime without requiring EXTRA_PIP_PACKAGES. Fix thread-unsafe pattern in caching._get_cached() where _locks.get(tool_name, threading.Lock()) created a new ephemeral lock on each call when the key was missing, allowing concurrent threads to bypass mutual exclusion. --- requirements.txt | 1 + src/caching.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3093f74..410c921 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ fastmcp[http]==3.2.0 boto3==1.38.13 gitpython==3.1.44 prometheus_client==0.22.1 +requests>=2.31 watchdog==6.0.0 diff --git a/src/caching.py b/src/caching.py index af2e2ae..e764b49 100644 --- a/src/caching.py +++ b/src/caching.py @@ -53,7 +53,10 @@ def _get_cached(tool_name: str, key: str, ttl: float) -> tuple[bool, object]: if tool_name not in _caches: return (False, None) - with _locks.get(tool_name, threading.Lock()): + if tool_name not in _locks: + _locks[tool_name] = threading.Lock() + + with _locks[tool_name]: entry = _caches[tool_name].get(key) if entry is None: return (False, None)