FastAPI-boilerplate icon indicating copy to clipboard operation
FastAPI-boilerplate copied to clipboard

Redis client not found when created background tasks in Swagger

Open scottyeung opened this issue 1 year ago • 4 comments

Describe the bug or question A clear and concise description of what the bug or question is.

To Reproduce Please provide a self-contained, minimal, and reproducible example of your use case

async def is_rate_limited(db: AsyncSession, user_id: int, path: str, limit: int, period: int) -> bool:
    if client is None:
        logger.error("Redis client is not initialized.")
        raise Exception("Redis client is not initialized.")

Description Redis client was recognised as none when I tried to create background tasks in Swagger and caught exception in is_rate_limited

Screenshots Screenshot 2024-09-08 at 5 12 24 PM Screenshot 2024-09-08 at 5 12 36 PM Screenshot 2024-09-08 at 5 14 44 PM

Additional context Add any other context about the problem here.

scottyeung avatar Sep 08 '24 09:09 scottyeung

How did you run it? Using docker compose?

igorbenav avatar Sep 08 '24 12:09 igorbenav

How did you run it? Using docker compose?

Exactly, docker-compose. Did I miss anything?

scottyeung avatar Sep 08 '24 13:09 scottyeung

Having the exact same issue. Redis name in .env = redis , App started by docker compose up -d When trying to post a new task , getting raise Exception("Redis client is not initialized.")=

studentNinja avatar Sep 12 '24 15:09 studentNinja

I think the issue is that all the Redis connections and the pool are tied to the cache in setup.py, which means that anyone who isn't using the cache can't get to them.

I came up with a temporary fix. It's not ideal, but it does the job. I moved everything, like the is_rate_limited function, into cache.py, and now it works just fine.

yucelz avatar Oct 03 '24 19:10 yucelz

With our without cache, i'm still having the same exact issue too. Upon debugging, I can see that the Redis rate_limit.client instantiated when the application is starting. Screenshot 2024-11-28 at 2 44 45 PM

However, the Redis client object somehow gets destroy and become None when the API endpoint is called: Screenshot 2024-11-28 at 2 45 31 PM

The issue only occurs on redis rate limiter object, but not on redis cache object

mlm-master avatar Nov 28 '24 07:11 mlm-master

Hello, I have exactly the same problem but I absolutely need rate_limiter to work for my application. Has a solution been found that would help me a lot? Thanks in advance

ThomasRoyer24 avatar Feb 09 '25 15:02 ThomasRoyer24

I'll take a look and fix it

igorbenav avatar Feb 09 '25 16:02 igorbenav

I'll take a look and fix it

thx a lot

ThomasRoyer24 avatar Feb 09 '25 16:02 ThomasRoyer24

Simply adding my voice to those that would like to see a solution with the rate_limiter intact.

cdot65 avatar Feb 10 '25 11:02 cdot65

Hey everyone!

Just submitted a fix for the rate limiter initialization issues. The Redis client was failing to initialize properly due to race conditions with Uvicorn's auto-reload feature.

The main change is moving from module-level variables to a class-based singleton pattern.

Breaking change: If you're importing the Redis client directly from rate_limit.py, you'll need to update your imports to use the new RateLimiter class and some other changes you can see here.

igorbenav avatar Feb 10 '25 22:02 igorbenav

Hey everyone!

Just submitted a fix for the rate limiter initialization issues. The Redis client was failing to initialize properly due to race conditions with Uvicorn's auto-reload feature.

The main change is moving from module-level variables to a class-based singleton pattern.

Breaking change: If you're importing the Redis client directly from rate_limit.py, you'll need to update your imports to use the new RateLimiter class and some other changes you can see here.

thx for fixing. I just have this little bug now:

2025-02-11 18:19:36 backend-1        |     async with self.lifespan_context(app) as maybe_state:
2025-02-11 18:19:36 backend-1        |   File "/usr/local/lib/python3.11/contextlib.py", line 217, in __aexit__
2025-02-11 18:19:36 backend-1        |     await anext(self.gen)
2025-02-11 18:19:36 backend-1        |   File "/backend/src/app/core/setup.py", line 123, in lifespan
2025-02-11 18:19:36 backend-1        |     await close_redis_rate_limit_pool()
2025-02-11 18:19:36 backend-1        |   File "/backend/src/app/core/setup.py", line 67, in close_redis_rate_limit_pool
2025-02-11 18:19:36 backend-1        |     await rate_limit.client.aclose()  # type: ignore
2025-02-11 18:19:36 backend-1        |           ^^^^^^^^^^^^^^^^^
2025-02-11 18:19:36 backend-1        | AttributeError: module 'app.core.utils.rate_limit' has no attribute 'client'

ThomasRoyer24 avatar Feb 11 '25 17:02 ThomasRoyer24

Hey, @ThomasRoyer24, just fixed it here #163.

igorbenav avatar Feb 12 '25 01:02 igorbenav