Skip to content

Commit

Permalink
[FIX] fastapi: Ensure thread safety of the FastAPI app cache
Browse files Browse the repository at this point in the history
defaultdict in python is not thread safe. Since this data structure
is used to store the cache of FastAPI apps, we must ensure that the
access to this cache is thread safe. This is done by using a lock
to protect the access to the cache.
  • Loading branch information
lmignon committed Jan 10, 2025
1 parent 2db95d5 commit 289868d
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions fastapi/pools/fastapi_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL).

import queue
import threading
from collections import defaultdict
from contextlib import contextmanager
from typing import Generator
Expand All @@ -16,18 +17,25 @@ def __init__(self):
self._queue_by_db_by_root_path: dict[
str, dict[str, queue.Queue[FastAPI]]
] = defaultdict(lambda: defaultdict(queue.Queue))
self._lock = threading.Lock()

def __get_app(self, env: Environment, root_path: str) -> FastAPI:
def __get_pool(self, env: Environment, root_path: str) -> queue.Queue[FastAPI]:
db_name = env.cr.dbname
with self._lock:
# default dict is not thread safe but the use
return self._queue_by_db_by_root_path[db_name][root_path]

def __get_app(self, env: Environment, root_path: str) -> FastAPI:
pool = self.__get_pool(env, root_path)
try:
return self._queue_by_db_by_root_path[db_name][root_path].get_nowait()
return pool.get_nowait()
except queue.Empty:
env["fastapi.endpoint"].sudo()
return env["fastapi.endpoint"].sudo().get_app(root_path)

def __return_app(self, env: Environment, app: FastAPI, root_path: str) -> None:
db_name = env.cr.dbname
self._queue_by_db_by_root_path[db_name][root_path].put(app)
pool = self.__get_pool(env, root_path)
pool.put(app)

@contextmanager
def get_app(
Expand Down

0 comments on commit 289868d

Please sign in to comment.