From 984337b35bdca6466a91cfb63dbb2297aec1e0f0 Mon Sep 17 00:00:00 2001 From: isharak7m <192635824+isharak7m@users.noreply.github.com> Date: Sat, 12 Sep 2026 10:30:40 +0530 Subject: [PATCH] fix: atomic token cache swap to eliminate race condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced _token_cache.clear() + _token_cache.update(new_map) with an atomic reference swap (_token_cache = dict(new_map)). The two-step mutate approach had a window where the dict was empty — any request hitting the reader at line 428 during that window would see zero candidates and return 401. Python's GIL makes the reference assignment atomic: readers always see either the old fully-populated dict or the new one, never an empty state. --- app.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index bb4f51ffb..80eb83c85 100644 --- a/app.py +++ b/app.py @@ -313,6 +313,7 @@ if AUTH_ENABLED: def _refresh_token_cache(): """Rebuild the prefix→[(id,hash)] map from the DB.""" + global _token_cache from collections import defaultdict new_map = defaultdict(list) db = SessionLocal() @@ -331,8 +332,8 @@ if AUTH_ENABLED: new_map[r.token_prefix].append((r.id, r.token_hash, owner_key, scopes)) finally: db.close() - _token_cache.clear() - _token_cache.update(new_map) + _token_cache = dict(new_map) + app.state._token_cache = _token_cache app.state._token_cache_dirty = False # Headers that prove a request was forwarded by a proxy/tunnel (cloudflared,