"""ChatSession model for managing user chat sessions.""" from datetime import datetime, timedelta from sqlalchemy import Column, String, DateTime, Integer, Boolean, JSON from sqlalchemy.orm import relationship from .base import BaseModel, db, GUID class ChatSession(BaseModel): """Model for managing user chat sessions.""" __tablename__ = 'chat_sessions' # Core session fields user_id = Column(GUID(), nullable=False, index=True) language = Column(String(50), nullable=False, default='python') # Activity tracking last_active = Column(DateTime, default=datetime.utcnow, nullable=False, index=True) message_count = Column(Integer, default=0, nullable=False) is_active = Column(Boolean, default=True, nullable=False, index=True) # Session metadata session_metadata = Column(JSON, default=dict) # Additional session context, preferences, etc. # Relationships messages = relationship("Message", back_populates="session", cascade="all, delete-orphan") language_context = relationship("LanguageContext", back_populates="session", uselist=False, cascade="all, delete-orphan") def __init__(self, user_id, language='python', session_metadata=None): """Initialize a new chat session.""" super().__init__() self.user_id = user_id self.language = language self.last_active = datetime.utcnow() self.message_count = 0 self.is_active = True self.session_metadata = session_metadata or {} def update_activity(self): """Update the last active timestamp.""" self.last_active = datetime.utcnow() db.session.commit() def increment_message_count(self): """Increment the message count for this session.""" self.message_count += 1 self.update_activity() def set_language(self, language): """Set the programming language for this session.""" self.language = language self.update_activity() def deactivate(self): """Mark the session as inactive.""" self.is_active = False db.session.commit() def is_expired(self, timeout_seconds=3600): """Check if the session has expired based on last activity.""" if not self.last_active: return True expiry_time = self.last_active + timedelta(seconds=timeout_seconds) return datetime.utcnow() > expiry_time def get_recent_messages(self, limit=10): """Get recent messages for this session.""" # Import here to avoid circular imports from .message import Message return (db.session.query(Message) .filter(Message.session_id == self.id) .order_by(Message.timestamp.desc()) .limit(limit) .all()) def to_dict(self): """Convert session to dictionary with formatted timestamps.""" data = super().to_dict() # Format timestamps as ISO strings for JSON serialization if self.last_active: data['last_active'] = self.last_active.isoformat() return data @classmethod def create_session(cls, user_id, language='python', session_metadata=None): """Create a new chat session.""" session = cls(user_id=user_id, language=language, session_metadata=session_metadata) db.session.add(session) db.session.commit() return session @classmethod def get_active_sessions(cls, user_id=None): """Get all active sessions, optionally filtered by user.""" query = db.session.query(cls).filter(cls.is_active == True) if user_id: query = query.filter(cls.user_id == user_id) return query.all() @classmethod def cleanup_expired_sessions(cls, timeout_seconds=3600): """Clean up expired sessions.""" cutoff_time = datetime.utcnow() - timedelta(seconds=timeout_seconds) expired_sessions = (db.session.query(cls) .filter(cls.last_active < cutoff_time) .filter(cls.is_active == True) .all()) for session in expired_sessions: session.deactivate() return len(expired_sessions) def __repr__(self): """String representation of the session.""" return f""