11import logging
22import config
33import redis
4+ from redis .connection import ConnectionPool
5+ import threading
6+
7+ # Global connection pool - thread-safe singleton
8+ _connection_pool = None
9+ _pool_lock = threading .Lock ()
10+
11+
12+ def get_connection_pool ():
13+ """
14+ Get or create Redis connection pool (thread-safe singleton).
15+ """
16+ global _connection_pool
17+
18+ if _connection_pool is None :
19+ with _pool_lock :
20+ if _connection_pool is None :
21+ try :
22+ # Connection pool configuration
23+ pool_kwargs = {
24+ "max_connections" : 50 ,
25+ "retry_on_timeout" : True ,
26+ "socket_connect_timeout" : 5 ,
27+ "socket_timeout" : 5 ,
28+ "health_check_interval" : 30 ,
29+ }
30+
31+ # try connection string, or default to separate REDIS_* env vars
32+ if config .redis_url :
33+ _connection_pool = ConnectionPool .from_url (
34+ config .redis_url , db = config .redis_database , ** pool_kwargs
35+ )
36+ elif config .redis_password :
37+ _connection_pool = ConnectionPool (
38+ host = config .redis_host ,
39+ port = config .redis_port ,
40+ password = config .redis_password ,
41+ db = config .redis_database ,
42+ ** pool_kwargs ,
43+ )
44+ else :
45+ _connection_pool = ConnectionPool (
46+ host = config .redis_host ,
47+ port = config .redis_port ,
48+ db = config .redis_database ,
49+ ** pool_kwargs ,
50+ )
51+
52+ logging .info ("Redis connection pool created successfully" )
53+
54+ except Exception as error :
55+ logging .error (f"Failed to create Redis connection pool: { error } " )
56+ return None
57+
58+ return _connection_pool
459
560
661def connect ():
762 """
8- Parse redis config and connect .
63+ Get Redis connection from pool .
964 """
65+ pool = get_connection_pool ()
66+ if pool is None :
67+ return None
1068
1169 try :
12- # try connection string, or default to separate REDIS_* env vars
13- if config .redis_url :
14- rds = redis .Redis .from_url (config .redis_url , db = config .redis_database )
15-
16- elif config .redis_password :
17- rds = redis .Redis (
18- host = config .redis_host ,
19- port = config .redis_port ,
20- password = config .redis_password ,
21- db = config .redis_database ,
22- )
23- else :
24- rds = redis .Redis (
25- host = config .redis_host , port = config .redis_port , db = config .redis_database
26- )
27-
70+ return redis .Redis (connection_pool = pool )
2871 except Exception as error :
29- logging .error ("Failed to connect to Redis with error: " + error )
30- return False
31-
32- return rds
72+ logging .error (f"Failed to get Redis connection from pool: { error } " )
73+ return None
3374
3475
3576def read (key ):
3677 """
3778 Read specified key from Redis.
3879 """
39-
4080 rds = connect ()
4181
82+ if rds is None :
83+ logging .error (f"Failed to get Redis connection for key: { key } " )
84+ return False
85+
4286 try :
43- # get info from cache
87+ # get info from cache with timeout
4488 data = rds .get (key )
4589
4690 # return False if not found
@@ -53,25 +97,40 @@ def read(key):
5397 # return data from Redis
5498 return data
5599
100+ except redis .ConnectionError as conn_error :
101+ logging .error (
102+ f"Redis connection error while reading key { key } : { conn_error } " ,
103+ extra = {"key" : key , "error_type" : "connection_error" },
104+ )
105+ return False
106+ except redis .TimeoutError as timeout_error :
107+ logging .error (
108+ f"Redis timeout error while reading key { key } : { timeout_error } " ,
109+ extra = {"key" : key , "error_type" : "timeout_error" },
110+ )
111+ return False
56112 except Exception as redis_error :
57- # print query parse error and return empty dict
58113 logging .error (
59- "An error occured while trying to read and decode from Redis" ,
60- extra = {"key" : key , "error_msg" : redis_error },
114+ f"Unexpected error while reading from Redis key { key } : { redis_error } " ,
115+ extra = {
116+ "key" : key ,
117+ "error_type" : "unexpected_error" ,
118+ "error_msg" : str (redis_error ),
119+ },
61120 )
62- logging .error (redis_error )
63-
64- # return failed status
65- return False
121+ return False
66122
67123
68124def write (key , data ):
69125 """
70126 Write specified key to Redis.
71127 """
72-
73128 rds = connect ()
74129
130+ if rds is None :
131+ logging .error (f"Failed to get Redis connection for key: { key } " )
132+ return False
133+
75134 # write data and set ttl
76135 try :
77136 expiration = int (config .cache_expiration )
@@ -82,43 +141,70 @@ def write(key, data):
82141 else :
83142 rds .set (key , data , ex = expiration )
84143
85- # return succes status
144+ # return success status
86145 return True
87146
147+ except redis .ConnectionError as conn_error :
148+ logging .error (
149+ f"Redis connection error while writing key { key } : { conn_error } " ,
150+ extra = {"key" : key , "error_type" : "connection_error" },
151+ )
152+ return False
153+ except redis .TimeoutError as timeout_error :
154+ logging .error (
155+ f"Redis timeout error while writing key { key } : { timeout_error } " ,
156+ extra = {"key" : key , "error_type" : "timeout_error" },
157+ )
158+ return False
88159 except Exception as redis_error :
89- # print query parse error and return empty dict
90160 logging .error (
91- "An error occured while trying to write to Redis cache" ,
92- extra = {"key" : key , "error_msg" : redis_error },
161+ f"Unexpected error while writing to Redis key { key } : { redis_error } " ,
162+ extra = {
163+ "key" : key ,
164+ "error_type" : "unexpected_error" ,
165+ "error_msg" : str (redis_error ),
166+ },
93167 )
94- logging .error (redis_error )
95-
96- # return fail status
97- return False
168+ return False
98169
99170
100171def increment (key , amount = 1 ):
101172 """
102- Increment value of amount to
103- specified key to Redis.
173+ Increment value of amount to specified key in Redis.
104174 """
105-
106175 rds = connect ()
107176
177+ if rds is None :
178+ logging .error (f"Failed to get Redis connection for key: { key } " )
179+ return False
180+
108181 # increment data of key
109182 try :
110183 # increment and set new value
111184 rds .incrby (key , amount )
112185
113- # return succes status
186+ # return success status
114187 return True
115188
189+ except redis .ConnectionError as conn_error :
190+ logging .error (
191+ f"Redis connection error while incrementing key { key } : { conn_error } " ,
192+ extra = {"key" : key , "error_type" : "connection_error" },
193+ )
194+ return False
195+ except redis .TimeoutError as timeout_error :
196+ logging .error (
197+ f"Redis timeout error while incrementing key { key } : { timeout_error } " ,
198+ extra = {"key" : key , "error_type" : "timeout_error" },
199+ )
200+ return False
116201 except Exception as redis_error :
117- # print query parse error and return empty dict
118202 logging .error (
119- "An error occured while trying to increment value in Redis cache" ,
120- extra = {"key" : key , "error_msg" : redis_error },
203+ f"Unexpected error while incrementing Redis key { key } : { redis_error } " ,
204+ extra = {
205+ "key" : key ,
206+ "error_type" : "unexpected_error" ,
207+ "error_msg" : str (redis_error ),
208+ },
121209 )
122-
123- # return fail status
124- return False
210+ return False
0 commit comments