Fix redis ssl issues 2

This commit is contained in:
2026-01-24 19:28:29 +01:00
parent 08f84e951a
commit c56c558618
11 changed files with 174 additions and 122 deletions

View File

@@ -3,25 +3,111 @@ Redis client initialization and connection management
Provides standardized Redis connection for all services
"""
import ssl
import redis.asyncio as redis
from typing import Optional
from typing import Optional, Dict, Any
import structlog
from contextlib import asynccontextmanager
logger = structlog.get_logger()
def get_ssl_kwargs_for_url(redis_url: str) -> Dict[str, Any]:
"""
Get SSL kwargs for redis.from_url() based on the URL scheme.
Handles self-signed certificates by disabling certificate verification
when using rediss:// (TLS-enabled) URLs.
Args:
redis_url: Redis connection URL (redis:// or rediss://)
Returns:
Dict with SSL configuration kwargs
"""
if redis_url and redis_url.startswith("rediss://"):
return {
"ssl_cert_reqs": ssl.CERT_NONE, # Disable certificate verification
"ssl_ca_certs": None, # Don't require CA certificates
"ssl_certfile": None, # Don't require client cert
"ssl_keyfile": None, # Don't require client key
}
return {}
class RedisConnectionManager:
"""
Manages Redis connections with connection pooling and error handling
Thread-safe singleton pattern for sharing connections across service
Manages Redis connections with connection pooling and error handling.
Thread-safe singleton pattern for sharing connections across service.
Usage:
# Option 1: Using class method (recommended for new code)
manager = await RedisConnectionManager.create(redis_url)
client = manager.get_client()
# Option 2: Using instance method
manager = RedisConnectionManager()
await manager.initialize(redis_url)
client = manager.get_client()
# Don't forget to close when done
await manager.close()
"""
def __init__(self):
self._client: Optional[redis.Redis] = None
self._pool: Optional[redis.ConnectionPool] = None
self._redis_url: Optional[str] = None
self.logger = logger
@classmethod
async def create(
cls,
redis_url: str,
db: int = 0,
max_connections: int = 50,
decode_responses: bool = False,
retry_on_timeout: bool = True,
socket_keepalive: bool = True,
health_check_interval: int = 30
) -> "RedisConnectionManager":
"""
Factory method to create and initialize a RedisConnectionManager.
This is the recommended way to create Redis connections across all services.
Handles SSL/TLS configuration automatically for self-signed certificates.
Args:
redis_url: Redis connection URL (redis:// or rediss://)
db: Database number (0-15)
max_connections: Maximum connections in pool
decode_responses: Automatically decode responses to strings
retry_on_timeout: Retry on timeout errors
socket_keepalive: Enable TCP keepalive
health_check_interval: Health check interval in seconds
Returns:
Initialized RedisConnectionManager
Example:
from shared.redis_utils import RedisConnectionManager
manager = await RedisConnectionManager.create(settings.REDIS_URL)
client = manager.get_client()
await client.ping()
"""
instance = cls()
await instance.initialize(
redis_url=redis_url,
db=db,
max_connections=max_connections,
decode_responses=decode_responses,
retry_on_timeout=retry_on_timeout,
socket_keepalive=socket_keepalive,
health_check_interval=health_check_interval,
)
return instance
async def initialize(
self,
redis_url: str,
@@ -45,8 +131,9 @@ class RedisConnectionManager:
health_check_interval: Health check interval in seconds
"""
try:
# Create connection pool
# Handle SSL parameters for self-signed certificates
self._redis_url = redis_url
# Create connection pool with SSL handling for self-signed certificates
connection_kwargs = {
'db': db,
'max_connections': max_connections,
@@ -55,16 +142,10 @@ class RedisConnectionManager:
'socket_keepalive': socket_keepalive,
'health_check_interval': health_check_interval
}
# If using SSL/TLS, add SSL parameters to handle self-signed certificates
if redis_url.startswith('rediss://'):
connection_kwargs.update({
'ssl_cert_reqs': None, # Disable certificate verification
'ssl_ca_certs': None, # Don't require CA certificates
'ssl_certfile': None, # Don't require client cert
'ssl_keyfile': None # Don't require client key
})
# Add SSL kwargs for self-signed certificates (using shared helper)
connection_kwargs.update(get_ssl_kwargs_for_url(redis_url))
self._pool = redis.ConnectionPool.from_url(
redis_url,
**connection_kwargs