Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commiteac61ed

Browse files
authored
improved redis singleton (#106)
1 parent5dbf134 commiteac61ed

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

‎src/backend/cache/redis_client.py‎

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
importos
2+
importasyncio
23
fromredisimportasyncioasaioredis
34
fromdotenvimportload_dotenv
45

@@ -15,30 +16,55 @@ class RedisClient:
1516
"""Service for managing Redis connections with proper lifecycle management."""
1617

1718
_instance=None
19+
_client=None
20+
_lock=asyncio.Lock()
1821

1922
@classmethod
2023
asyncdefget_instance(cls)->aioredis.Redis:
21-
"""Get or create a Redis client instance."""
22-
ifcls._instanceisNone:
23-
cls._instance=cls()
24-
awaitcls._instance.initialize()
25-
returncls._instance.client
24+
"""Get or create a Redis client instance with proper singleton behavior."""
25+
ifcls._clientisNone:
26+
asyncwithcls._lock:
27+
# Double-check pattern to prevent race conditions
28+
ifcls._clientisNone:
29+
ifcls._instanceisNone:
30+
cls._instance=cls()
31+
awaitcls._instance.initialize()
32+
returncls._client
2633

27-
def__init__(self):
28-
self.client=None
2934

3035
asyncdefinitialize(self)->None:
31-
"""Initialize the Redis client."""
32-
self.client=aioredis.from_url(
33-
REDIS_URL,
34-
password=REDIS_PASSWORD,
35-
decode_responses=True,
36-
health_check_interval=30
37-
)
38-
39-
asyncdefclose(self)->None:
40-
"""Close the Redis client connection."""
41-
ifself.client:
42-
awaitself.client.close()
43-
self.client=None
44-
print("Redis client closed.")
36+
"""Initialize the Redis client with connection pool limits."""
37+
ifRedisClient._clientisNone:
38+
try:
39+
RedisClient._client=aioredis.from_url(
40+
REDIS_URL,
41+
password=REDIS_PASSWORD,
42+
decode_responses=True,
43+
health_check_interval=30,
44+
max_connections=20,# Limit connection pool size
45+
retry_on_timeout=True,
46+
socket_keepalive=True,
47+
socket_keepalive_options={}
48+
)
49+
print(f"Redis client initialized with connection pool (max 20 connections)")
50+
51+
# Test the connection
52+
awaitRedisClient._client.ping()
53+
54+
exceptExceptionase:
55+
print(f"Failed to initialize Redis client:{e}")
56+
RedisClient._client=None
57+
raise
58+
59+
@classmethod
60+
asyncdefclose(cls)->None:
61+
"""Close the Redis client connection and reset singleton state."""
62+
ifcls._client:
63+
try:
64+
awaitcls._client.close()
65+
print("Redis client closed.")
66+
exceptExceptionase:
67+
print(f"Error closing Redis client:{e}")
68+
finally:
69+
cls._client=None
70+
cls._instance=None

‎src/backend/main.py‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ async def lifespan(app: FastAPI):
4949

5050
# Initialize Redis client and verify connection
5151
redis=awaitRedisClient.get_instance()
52-
awaitredis.ping()
5352
print("Redis connection established successfully")
5453

5554
# Initialize the canvas worker
@@ -58,9 +57,8 @@ async def lifespan(app: FastAPI):
5857

5958
yield
6059

61-
# Shutdown
6260
awaitCanvasWorker.shutdown_instance()
63-
awaitredis.close()
61+
awaitRedisClient.close()
6462
awaitengine.dispose()
6563

6664
app=FastAPI(lifespan=lifespan)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp