BrianIsaac's picture
feat: implement P1 features and production infrastructure
76897aa
"""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()