""" Comprehensive User Data Cache Model Caches expensive comprehensive user data operations to improve performance. """ from sqlalchemy import Column, Integer, String, DateTime, JSON, Index, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from datetime import datetime, timedelta import hashlib import json Base = declarative_base() class ComprehensiveUserDataCache(Base): """Cache for comprehensive user data to avoid redundant expensive operations.""" __tablename__ = "comprehensive_user_data_cache" id = Column(Integer, primary_key=True) user_id = Column(Integer, nullable=False) strategy_id = Column(Integer, nullable=True) data_hash = Column(String(64), nullable=False) # For cache invalidation comprehensive_data = Column(JSON, nullable=False) created_at = Column(DateTime, default=datetime.utcnow) expires_at = Column(DateTime, nullable=False) last_accessed = Column(DateTime, default=datetime.utcnow) access_count = Column(Integer, default=0) # Indexes for fast lookups __table_args__ = ( Index('idx_user_strategy', 'user_id', 'strategy_id'), Index('idx_expires_at', 'expires_at'), Index('idx_data_hash', 'data_hash'), ) def __repr__(self): return f"" @staticmethod def generate_data_hash(user_id: int, strategy_id: int = None, **kwargs) -> str: """Generate a hash for cache invalidation based on input parameters.""" data_string = f"{user_id}_{strategy_id}_{json.dumps(kwargs, sort_keys=True)}" return hashlib.sha256(data_string.encode()).hexdigest() @staticmethod def get_default_expiry() -> datetime: """Get default expiry time (1 hour from now).""" return datetime.utcnow() + timedelta(hours=1) def is_expired(self) -> bool: """Check if the cache entry has expired.""" return datetime.utcnow() > self.expires_at def touch(self): """Update last accessed time and increment access count.""" self.last_accessed = datetime.utcnow() self.access_count += 1 def to_dict(self) -> dict: """Convert cache entry to dictionary.""" return { "id": self.id, "user_id": self.user_id, "strategy_id": self.strategy_id, "data_hash": self.data_hash, "comprehensive_data": self.comprehensive_data, "created_at": self.created_at.isoformat(), "expires_at": self.expires_at.isoformat(), "last_accessed": self.last_accessed.isoformat(), "access_count": self.access_count }