redis handler implemented Servies Task has redis object
This commit is contained in:
@@ -88,6 +88,13 @@ class BuildingCluster(BaseModel):
|
||||
build_parts: List['BuildPart'] = []
|
||||
|
||||
|
||||
class BuildRequirements(BaseModel):
|
||||
|
||||
building_count: int
|
||||
living_space: int
|
||||
build_parts: int
|
||||
|
||||
|
||||
# Update forward references for models with circular dependencies
|
||||
BuildPart.update_forward_refs()
|
||||
BuildingCluster.update_forward_refs()
|
||||
|
||||
@@ -4,8 +4,7 @@ from json import loads, dumps
|
||||
from contextlib import contextmanager
|
||||
from time import sleep
|
||||
from redis import Redis, RedisError, ConnectionError as RedisConnectionError
|
||||
|
||||
from config import RedisConfig
|
||||
from .config import RedisConfig
|
||||
|
||||
|
||||
logger = logging.getLogger('RedisHandler')
|
||||
@@ -43,35 +42,28 @@ class RedisHandler:
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
# Initialize only once
|
||||
if self._initialized:
|
||||
return
|
||||
|
||||
# Initialize Redis client with retry logic
|
||||
self.redis_client = self._create_redis_client()
|
||||
self.redis_connected = self._check_redis_connection()
|
||||
self._initialized = True
|
||||
|
||||
def _create_redis_client(self):
|
||||
"""Create a Redis client with connection retry"""
|
||||
max_retries = 5
|
||||
retry_delay = 5
|
||||
|
||||
max_retries, retry_delay = 5, 5
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
client = Redis(**RedisConfig.as_dict())
|
||||
client.ping() # Test the connection
|
||||
client.ping()
|
||||
logger.info("Redis connection established successfully")
|
||||
return client
|
||||
except (RedisConnectionError, RedisError) as e:
|
||||
if attempt < max_retries - 1:
|
||||
logger.warning(f"Redis connection attempt {attempt + 1} failed: {str(e)}. Retrying in {retry_delay} seconds...")
|
||||
sleep(retry_delay)
|
||||
retry_delay *= 2 # Exponential backoff
|
||||
retry_delay *= 2
|
||||
else:
|
||||
logger.error(f"Failed to connect to Redis after {max_retries} attempts: {str(e)}")
|
||||
# Continue with a new Redis client instance even if ping fails
|
||||
# This allows the service to start and retry connections later
|
||||
return Redis(**RedisConfig.as_dict())
|
||||
|
||||
def _check_redis_connection(self) -> bool:
|
||||
@@ -81,11 +73,11 @@ class RedisHandler:
|
||||
return True
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
|
||||
def ping(self):
|
||||
"""Ping Redis server to check connection"""
|
||||
return self.redis_client.ping()
|
||||
|
||||
|
||||
def sadd(self, key: str, value):
|
||||
"""Add a value to a Redis set"""
|
||||
return self.redis_client.sadd(key, value)
|
||||
@@ -93,11 +85,22 @@ class RedisHandler:
|
||||
def ismember(self, key: str, value):
|
||||
"""Check if a value is a member of a Redis set"""
|
||||
return self.redis_client.sismember(key, value)
|
||||
|
||||
|
||||
def get(self, key: str):
|
||||
"""Get a value from Redis by key"""
|
||||
return self.redis_client.get(key)
|
||||
|
||||
|
||||
def get_json(self, key: str) -> dict:
|
||||
"""Get a value from Redis by key"""
|
||||
obj = self.redis_client.get(key)
|
||||
if obj:
|
||||
return loads(obj)
|
||||
return None
|
||||
|
||||
def set_json(self, key: str, value):
|
||||
"""Set a key-value pair in Redis"""
|
||||
return self.redis_client.set(key, dumps(value))
|
||||
|
||||
def set(self, key: str, value):
|
||||
"""Set a key-value pair in Redis"""
|
||||
return self.redis_client.set(key, value)
|
||||
@@ -139,7 +142,7 @@ class RedisHandler:
|
||||
logger.error(f"Failed to re-establish Redis connection: {str(e)}")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@classmethod
|
||||
def handle_reconnection(cls, consecutive_errors=0, max_consecutive_errors=5):
|
||||
"""
|
||||
@@ -151,12 +154,9 @@ class RedisHandler:
|
||||
tuple: (RedisHandler instance, bool indicating if extended sleep is needed)
|
||||
"""
|
||||
try:
|
||||
# Get a fresh instance (will reconnect internally)
|
||||
instance = cls()
|
||||
instance.redis_connected = instance._check_redis_connection()
|
||||
logger.info("Recreated Redis handler using singleton pattern")
|
||||
|
||||
# Determine if extended sleep is needed
|
||||
need_extended_sleep = consecutive_errors >= max_consecutive_errors
|
||||
if need_extended_sleep:
|
||||
logger.warning(f"Hit {max_consecutive_errors} consecutive Redis errors, taking longer pause")
|
||||
@@ -165,3 +165,8 @@ class RedisHandler:
|
||||
logger.error(f"Failed to recreate Redis handler: {str(redis_retry_error)}")
|
||||
return None, consecutive_errors >= max_consecutive_errors
|
||||
|
||||
|
||||
class RedisSaveModels:
|
||||
|
||||
COMMENT_BUILDING_CLUSTER = "COMMENT:PARSER:BUILDING:CLUSTER"
|
||||
COMMENT_BUILDING_INFO = "COMMENT:PARSER:BUILDING:INFO"
|
||||
|
||||
@@ -6,8 +6,9 @@ import aio_pika
|
||||
|
||||
from aio_pika.abc import AbstractIncomingMessage
|
||||
from typing import Any, Dict, Awaitable, Callable, Optional, List
|
||||
from app.services.types.task import _MsgCtx, _MSG_CTX
|
||||
from app.services.types.queue import Enqueue
|
||||
|
||||
from services.types.task import _MsgCtx, _MSG_CTX
|
||||
from services.types.queue import Enqueue
|
||||
|
||||
|
||||
class ServiceBaseAsync:
|
||||
|
||||
Reference in New Issue
Block a user