11"""Utilities for connecting to and managing Redis connections."""
22
3+ import logging
34from typing import Optional
45
56from pydantic_settings import BaseSettings
89
910redis_pool : Optional [aioredis .Redis ] = None
1011
12+ logger = logging .getLogger (__name__ )
13+
1114
1215class RedisSentinelSettings (BaseSettings ):
1316 """Configuration for connecting to Redis Sentinel."""
@@ -25,7 +28,7 @@ class RedisSentinelSettings(BaseSettings):
2528
2629
2730class RedisSettings (BaseSettings ):
28- """Configuration for connecting Redis Sentinel ."""
31+ """Configuration for connecting Redis."""
2932
3033 REDIS_HOST : str = ""
3134 REDIS_PORT : int = 6379
@@ -38,75 +41,71 @@ class RedisSettings(BaseSettings):
3841 REDIS_HEALTH_CHECK_INTERVAL : int = 30
3942
4043
41- # Select the Redis or Redis Sentinel configuration
42- redis_settings : BaseSettings = RedisSettings ()
43-
44+ # Configure only one Redis configuration
45+ sentinel_settings = RedisSentinelSettings ()
46+ standalone_settings = RedisSettings ()
4447
45- async def connect_redis (settings : Optional [RedisSettings ] = None ) -> aioredis .Redis :
46- """Return a Redis connection."""
47- global redis_pool
48- settings = settings or redis_settings
49-
50- if not settings .REDIS_HOST or not settings .REDIS_PORT :
51- return None
5248
53- if redis_pool is None :
54- pool = aioredis .ConnectionPool (
55- host = settings .REDIS_HOST ,
56- port = settings .REDIS_PORT ,
57- db = settings .REDIS_DB ,
58- max_connections = settings .REDIS_MAX_CONNECTIONS ,
59- decode_responses = settings .REDIS_DECODE_RESPONSES ,
60- retry_on_timeout = settings .REDIS_RETRY_TIMEOUT ,
61- health_check_interval = settings .REDIS_HEALTH_CHECK_INTERVAL ,
62- )
63- redis_pool = aioredis .Redis (
64- connection_pool = pool , client_name = settings .REDIS_CLIENT_NAME
65- )
66- return redis_pool
67-
68-
69- async def connect_redis_sentinel (
70- settings : Optional [RedisSentinelSettings ] = None ,
71- ) -> Optional [aioredis .Redis ]:
72- """Return a Redis Sentinel connection."""
49+ async def connect_redis () -> Optional [aioredis .Redis ]:
50+ """Return a Redis connection Redis or Redis Sentinel."""
7351 global redis_pool
7452
75- settings = settings or redis_settings
53+ if redis_pool is not None :
54+ return redis_pool
55+
56+ try :
57+ if sentinel_settings .REDIS_SENTINEL_HOSTS :
58+ hosts = [
59+ h .strip ()
60+ for h in sentinel_settings .REDIS_SENTINEL_HOSTS .split ("," )
61+ if h .strip ()
62+ ]
63+ ports = [
64+ int (p .strip ())
65+ for p in sentinel_settings .REDIS_SENTINEL_PORTS .split ("," )
66+ if p .strip ()
67+ ]
7668
77- if (
78- not settings .REDIS_SENTINEL_HOSTS
79- or not settings .REDIS_SENTINEL_PORTS
80- or not settings .REDIS_SENTINEL_MASTER_NAME
81- ):
82- return None
83-
84- hosts = [h .strip () for h in settings .REDIS_SENTINEL_HOSTS .split ("," ) if h .strip ()]
85- ports = [
86- int (p .strip ()) for p in settings .REDIS_SENTINEL_PORTS .split ("," ) if p .strip ()
87- ]
88-
89- if redis_pool is None :
90- try :
9169 sentinel = Sentinel (
9270 [(h , p ) for h , p in zip (hosts , ports )],
93- decode_responses = settings .REDIS_DECODE_RESPONSES ,
94- )
95- master = sentinel .master_for (
96- service_name = settings .REDIS_SENTINEL_MASTER_NAME ,
97- db = settings .REDIS_DB ,
98- decode_responses = settings .REDIS_DECODE_RESPONSES ,
99- retry_on_timeout = settings .REDIS_RETRY_TIMEOUT ,
100- client_name = settings .REDIS_CLIENT_NAME ,
101- max_connections = settings .REDIS_MAX_CONNECTIONS ,
102- health_check_interval = settings .REDIS_HEALTH_CHECK_INTERVAL ,
71+ decode_responses = sentinel_settings .REDIS_DECODE_RESPONSES ,
10372 )
104- redis_pool = master
10573
106- except Exception :
74+ redis_pool = sentinel .master_for (
75+ service_name = sentinel_settings .REDIS_SENTINEL_MASTER_NAME ,
76+ db = sentinel_settings .REDIS_DB ,
77+ decode_responses = sentinel_settings .REDIS_DECODE_RESPONSES ,
78+ retry_on_timeout = sentinel_settings .REDIS_RETRY_TIMEOUT ,
79+ client_name = sentinel_settings .REDIS_CLIENT_NAME ,
80+ max_connections = sentinel_settings .REDIS_MAX_CONNECTIONS ,
81+ health_check_interval = sentinel_settings .REDIS_HEALTH_CHECK_INTERVAL ,
82+ )
83+ logger .info ("Connected to Redis Sentinel" )
84+
85+ elif standalone_settings .REDIS_HOST :
86+ pool = aioredis .ConnectionPool (
87+ host = standalone_settings .REDIS_HOST ,
88+ port = standalone_settings .REDIS_PORT ,
89+ db = standalone_settings .REDIS_DB ,
90+ max_connections = standalone_settings .REDIS_MAX_CONNECTIONS ,
91+ decode_responses = standalone_settings .REDIS_DECODE_RESPONSES ,
92+ retry_on_timeout = standalone_settings .REDIS_RETRY_TIMEOUT ,
93+ health_check_interval = standalone_settings .REDIS_HEALTH_CHECK_INTERVAL ,
94+ )
95+ redis_pool = aioredis .Redis (
96+ connection_pool = pool , client_name = standalone_settings .REDIS_CLIENT_NAME
97+ )
98+ logger .info ("Connected to Redis" )
99+ else :
100+ logger .warning ("No Redis configuration found" )
107101 return None
108102
109- return redis_pool
103+ return redis_pool
104+
105+ except Exception as e :
106+ logger .error (f"Failed to connect to Redis: { e } " )
107+ redis_pool = None
108+ return None
110109
111110
112111async def save_self_link (
@@ -122,3 +121,32 @@ async def get_prev_link(redis: aioredis.Redis, token: Optional[str]) -> Optional
122121 if not token :
123122 return None
124123 return await redis .get (f"nav:self:{ token } " )
124+
125+
126+ async def redis_pagination_links (
127+ current_url : str , token : str , next_token : str , links : list
128+ ) -> None :
129+ """Handle Redis pagination."""
130+ redis = None
131+ try :
132+ redis = await connect_redis ()
133+ logger .info ("Redis connection established successfully" )
134+ except Exception as e :
135+ redis = None
136+ logger .warning (f"Redis connection failed: { e } " )
137+
138+ if redis :
139+ if next_token :
140+ await save_self_link (redis , next_token , current_url )
141+
142+ prev_link = await get_prev_link (redis , token )
143+ if prev_link :
144+ links .insert (
145+ 0 ,
146+ {
147+ "rel" : "prev" ,
148+ "type" : "application/json" ,
149+ "method" : "GET" ,
150+ "href" : prev_link ,
151+ },
152+ )
0 commit comments