import arrow from typing import Optional, List, Dict, Union from AllConfigs.main import MainConfig from Services.Redis.conn import redis_cli from Services.Redis.Models.base import RedisRow from Services.Redis.Models.response import RedisResponse class RedisActions: """Class for handling Redis operations with JSON data.""" @classmethod def get_expiry_time(cls, expiry_kwargs: Dict[str, int]) -> int: """Calculate expiry time in seconds from kwargs.""" time_multipliers = {"days": 86400, "hours": 3600, "minutes": 60, "seconds": 1} return sum( int(expiry_kwargs.get(unit, 0)) * multiplier for unit, multiplier in time_multipliers.items() ) @classmethod def set_expiry_time(cls, expiry_seconds: int) -> Dict[str, int]: """Convert total seconds back into a dictionary of time units.""" time_multipliers = {"days": 86400, "hours": 3600, "minutes": 60, "seconds": 1} result = {} for unit, multiplier in time_multipliers.items(): if expiry_seconds >= multiplier: result[unit], expiry_seconds = divmod(expiry_seconds, multiplier) return result @classmethod def resolve_expires_at(cls, redis_row: RedisRow) -> str: """Resolve expiry time for Redis key.""" expiry_time = redis_cli.ttl(redis_row.redis_key) if expiry_time == -1: return "Key has no expiry time." return arrow.now().shift(seconds=expiry_time).format(MainConfig.DATETIME_FORMAT) @classmethod def delete_key(cls, key: Union[Optional[str], Optional[bytes]]): try: redis_cli.delete(key) return RedisResponse( status=True, message="Value is deleted successfully.", ) except Exception as e: return RedisResponse( status=False, message="Value is not deleted successfully.", error=str(e), ) @classmethod def delete( cls, list_keys: List[Union[Optional[str], Optional[bytes]]] ) -> RedisResponse: try: regex = RedisRow().regex(list_keys=list_keys) json_get = redis_cli.scan_iter(match=regex) for row in list(json_get): redis_cli.delete(row) return RedisResponse( status=True, message="Values are deleted successfully.", ) except Exception as e: return RedisResponse( status=False, message="Values are not deleted successfully.", error=str(e), ) @classmethod def set_json( cls, list_keys: List[Union[str, bytes]], value: Optional[Union[Dict, List]], expires: Optional[Dict[str, int]] = None, ) -> RedisResponse: """Set JSON value in Redis with optional expiry.""" redis_row = RedisRow() redis_row.merge(set_values=list_keys) redis_row.feed(value) redis_row.expires_at_string = None redis_row.expires_at = None try: if expires: redis_row.expires_at = expires expiry_time = cls.get_expiry_time(expiry_kwargs=expires) redis_cli.setex( name=redis_row.redis_key, time=expiry_time, value=redis_row.value, ) redis_row.expires_at_string = str( arrow.now() .shift(seconds=expiry_time) .format(MainConfig.DATETIME_FORMAT) ) else: redis_cli.set(name=redis_row.redis_key, value=redis_row.value) return RedisResponse( status=True, message="Value is set successfully.", data=redis_row, ) except Exception as e: return RedisResponse( status=False, message="Value is not set successfully.", error=str(e), ) @classmethod def get_json( cls, list_keys: List[Union[Optional[str], Optional[bytes]]] ) -> RedisResponse: """Get JSON values from Redis using pattern matching.""" try: list_of_rows = [] regex = RedisRow.regex(list_keys=list_keys) json_get = redis_cli.scan_iter(match=regex) for row in list(json_get): redis_row = RedisRow() redis_row.set_key(key=row) redis_value = redis_cli.get(row) redis_value_expire = redis_cli.ttl(row) redis_row.expires_at = cls.set_expiry_time( expiry_seconds=int(redis_value_expire) ) redis_row.expires_at_string = cls.resolve_expires_at( redis_row=redis_row ) redis_row.feed(redis_value) list_of_rows.append(redis_row) if list_of_rows: return RedisResponse( status=True, message="Value is get successfully.", data=list_of_rows, ) return RedisResponse( status=False, message="Value is not get successfully.", data=list_of_rows, ) except Exception as e: return RedisResponse( status=False, message="Value is not get successfully.", error=str(e), )