From 796a2e6ca817c47aba9cff25112ea429c82b0b4f Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Mon, 15 Jun 2026 23:49:28 +0800 Subject: [PATCH] Fix: offload bcrypt.checkpw to thread pool to prevent blocking event loop bcrypt.checkpw is CPU-bound (~1.3s per call) and was running synchronously inside the async event loop, blocking ALL concurrent requests. With 5 API keys and 10 concurrent requests, this caused ~13s delay before any handler could start. --- .../api/routes/controller/dependencies/authentication.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gns3server/api/routes/controller/dependencies/authentication.py b/gns3server/api/routes/controller/dependencies/authentication.py index 1b3153698..9fdddd30c 100644 --- a/gns3server/api/routes/controller/dependencies/authentication.py +++ b/gns3server/api/routes/controller/dependencies/authentication.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import asyncio import logging import bcrypt @@ -64,7 +65,8 @@ async def get_user_from_token( api_keys_list = result.scalars().all() log.info(f"[CTRL-TIMING] get_user_from_token api_keys_count={len(api_keys_list)} elapsed={time.time()-_t0:.3f}s") for db_key in api_keys_list: - if bcrypt.checkpw(token.encode(), db_key.key_hash.encode()): + # bcrypt.checkpw is CPU-bound and blocks the event loop; run in thread + if await asyncio.to_thread(bcrypt.checkpw, token.encode(), db_key.key_hash.encode()): await api_keys_repo.update_last_used(db_key.api_key_id) user = await user_repo.get_user(db_key.user_id) if user: