""" Cache key generation utilities """ import hashlib import json from typing import Any, List, Optional def generate_cache_key(cache_type: str, key_params: Optional[List[str]], args: tuple, kwargs: dict) -> str: """ Generate cache key from function parameters Format: "{cache_type}:{param1_value}:{param2_value}:..." Args: cache_type: Type of cache (e.g., 'dashboard_summary', 'invoices') key_params: List of parameter names to include in key args: Positional arguments from function call kwargs: Keyword arguments from function call Returns: Cache key string Examples: generate_cache_key('schema', ['company_id'], (123,), {}) -> "schema:123" generate_cache_key('dashboard_summary', ['company', 'username'], (), {'company': '123', 'username': 'john'}) -> "dashboard_summary:123:john" generate_cache_key('invoices', ['company', 'invoice_type', 'status'], (123, 'CLIENTI', 'neplatite'), {}) -> "invoices:123:CLIENTI:neplatite" """ key_parts = [cache_type] if not key_params: # No specific params - use all args/kwargs (fallback) if args: key_parts.extend([str(arg) for arg in args]) if kwargs: # Sort kwargs for consistent key generation sorted_kwargs = sorted(kwargs.items()) key_parts.extend([f"{k}={v}" for k, v in sorted_kwargs]) else: # Extract specific params for i, param_name in enumerate(key_params): # Try to get from kwargs first if param_name in kwargs: value = kwargs[param_name] # Then try positional args elif i < len(args): value = args[i] else: # Parameter not found - use placeholder value = "none" key_parts.append(str(value)) return ":".join(key_parts) def generate_key_pattern(cache_type: str, company_id: Optional[int] = None) -> str: """ Generate cache key pattern for matching multiple keys Used for invalidation by type or company Args: cache_type: Type of cache company_id: Optional company ID to filter by Returns: Pattern string (prefix) Examples: generate_key_pattern('dashboard_summary') -> "dashboard_summary:" generate_key_pattern('dashboard_summary', 123) -> "dashboard_summary:123" """ if company_id is not None: return f"{cache_type}:{company_id}" return f"{cache_type}:" def hash_complex_params(params: dict) -> str: """ Generate hash for complex parameters (e.g., filters, queries) Used when cache key would be too long with full param values Args: params: Dictionary of parameters to hash Returns: 8-character hash string Example: filters = {'status': 'neplatite', 'date_from': '2024-01-01', 'date_to': '2024-12-31'} hash_complex_params(filters) -> "a3f8b2c1" """ # Sort keys for consistent hashing sorted_params = json.dumps(params, sort_keys=True) hash_obj = hashlib.sha256(sorted_params.encode()) # Return first 8 characters of hex digest return hash_obj.hexdigest()[:8] def extract_company_id_from_key(cache_key: str) -> Optional[int]: """ Extract company_id from cache key Assumes format: "cache_type:company_id:..." Args: cache_key: Cache key string Returns: Company ID or None if not found Example: extract_company_id_from_key("dashboard_summary:123:john") -> 123 """ parts = cache_key.split(":") if len(parts) >= 2: try: return int(parts[1]) except (ValueError, TypeError): pass return None def extract_cache_type_from_key(cache_key: str) -> str: """ Extract cache_type from cache key Args: cache_key: Cache key string Returns: Cache type (first part before colon) Example: extract_cache_type_from_key("dashboard_summary:123:john") -> "dashboard_summary" """ return cache_key.split(":")[0]