"""Cache factory for initialising caching infrastructure. This module provides factory functions and singleton instances for cache management across the application. """ import logging from typing import Optional from backend.caching.redis_cache import ( FinancialDataCacheManager, HybridCache, ) from backend.config import settings logger = logging.getLogger(__name__) class CacheFactory: """Factory for creating and managing cache instances. Provides singleton pattern for cache instances to ensure consistent cache usage across the application. """ _cache_instance: Optional[HybridCache] = None _manager_instance: Optional[FinancialDataCacheManager] = None @classmethod def get_cache(cls, force_new: bool = False) -> HybridCache: """Get or create HybridCache instance. Args: force_new: Force creation of new instance. Returns: HybridCache instance. """ if cls._cache_instance is None or force_new: cls._cache_instance = cls.create_cache() return cls._cache_instance @classmethod def get_manager(cls, force_new: bool = False) -> FinancialDataCacheManager: """Get or create FinancialDataCacheManager instance. Args: force_new: Force creation of new instance. Returns: FinancialDataCacheManager instance. """ if cls._manager_instance is None or force_new: cache = cls.get_cache() cls._manager_instance = FinancialDataCacheManager(cache) return cls._manager_instance @classmethod def create_cache(cls) -> HybridCache: """Create a new HybridCache instance from settings. Returns: Configured HybridCache instance. """ if not settings.cache_enabled: logger.info("Caching is disabled in settings") return HybridCache( redis_url=None, redis_token=None, enable_fallback=True, ) cache = HybridCache( redis_url=settings.upstash_redis_url, redis_token=settings.upstash_redis_token, enable_fallback=settings.cache_fallback_enabled, fallback_size=settings.cache_fallback_max_size, ) logger.info( f"Cache initialised with backend: {cache.stats.backend.value}" ) return cache @classmethod def reset(cls) -> None: """Reset singleton instances. Useful for testing or when configuration changes. """ cls._cache_instance = None cls._manager_instance = None logger.info("Cache factory reset") def get_cache() -> HybridCache: """Get global cache instance. Convenience function for accessing the singleton cache. Returns: HybridCache instance. Example: >>> from backend.caching.factory import get_cache >>> cache = get_cache() >>> cache.set("key", "value", ttl=300) >>> value = cache.get("key") """ return CacheFactory.get_cache() def get_cache_manager() -> FinancialDataCacheManager: """Get global cache manager instance. Convenience function for accessing the singleton cache manager. Returns: FinancialDataCacheManager instance. Example: >>> from backend.caching.factory import get_cache_manager >>> manager = get_cache_manager() >>> manager.cache_market_data("AAPL", {"price": 150.00}) >>> data = manager.get_market_data("AAPL") """ return CacheFactory.get_manager() # Global instances (initialised on first import) cache = get_cache() cache_manager = get_cache_manager()