Spaces:
Paused
Paused
| """ | |
| Flare – Session Management | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| • thread-safe SessionStore | |
| • state-machine alanları | |
| """ | |
| from __future__ import annotations | |
| import threading, uuid, time | |
| from datetime import datetime, timedelta | |
| from typing import Dict, List | |
| from utils import log | |
| class Session: | |
| """Single chat session.""" | |
| def __init__(self, project_name: str): | |
| self.session_id: str = str(uuid.uuid4()) | |
| self.project_name: str = project_name | |
| # flow state | |
| self.state: str = "idle" # idle | await_param | call_api | humanize | |
| self.last_intent: str | None = None | |
| self.awaiting_parameters: List[str] = [] | |
| self.missing_ask_count: int = 0 | |
| # data | |
| self.variables: Dict[str, str] = {} | |
| self.auth_tokens: Dict[str, Dict] = {} # api_name -> {token, expiry} | |
| # history | |
| self.chat_history: List[Dict[str, str]] = [] | |
| self.created_at: datetime = datetime.now() | |
| self.last_activity: datetime = datetime.now() | |
| def update_activity(self): | |
| """Update last activity timestamp""" | |
| self.last_activity = datetime.now() | |
| # -------- helper ---------- | |
| def add_turn(self, role: str, content: str): | |
| self.chat_history.append({"role": role, "content": content}) | |
| self.update_activity() # Activity güncellemesi eklendi | |
| if len(self.chat_history) > 20: | |
| self.chat_history.pop(0) | |
| # -------- reset flow ------ | |
| def reset_flow(self): | |
| self.state = "idle" | |
| self.last_intent = None | |
| self.awaiting_parameters.clear() | |
| self.missing_ask_count = 0 | |
| class SessionStore: | |
| """Thread-safe global store.""" | |
| def __init__(self): | |
| self._lock = threading.Lock() | |
| self._sessions: Dict[str, Session] = {} | |
| def create_session(self, project_name: str) -> Session: | |
| with self._lock: | |
| s = Session(project_name) | |
| self._sessions[s.session_id] = s | |
| log(f"🆕 Session created {s.session_id}") | |
| return s | |
| def get_session(self, sid: str) -> Session | None: | |
| with self._lock: | |
| return self._sessions.get(sid) | |
| def __contains__(self, sid: str) -> bool: | |
| return self.get_session(sid) is not None | |
| def cleanup_expired_sessions(self, timeout_minutes: int = 30): | |
| """Remove expired sessions""" | |
| with self._lock: | |
| now = datetime.now() | |
| expired = [] | |
| for sid, session in self._sessions.items(): | |
| if (now - session.last_activity).total_seconds() > timeout_minutes * 60: | |
| expired.append(sid) | |
| for sid in expired: | |
| del self._sessions[sid] | |
| log(f"🗑️ Expired session removed: {sid[:8]}...") | |
| if expired: | |
| log(f"📊 Active sessions: {len(self._sessions)}") | |
| session_store = SessionStore() | |
| # Cleanup thread başlat | |
| def start_session_cleanup(): | |
| def cleanup_loop(): | |
| while True: | |
| try: | |
| session_store.cleanup_expired_sessions() | |
| except Exception as e: | |
| log(f"❌ Session cleanup error: {e}") | |
| time.sleep(300) # 5 dakikada bir | |
| thread = threading.Thread(target=cleanup_loop, daemon=True) | |
| thread.start() | |
| log("🧹 Session cleanup thread started") | |