my-gradio-app / utils /session_store.py
Nguyen Trong Lap
Recreate history without binary blobs
eeb0f9c
"""
Session Store - Persistent storage for conversation memory
Saves and loads user sessions across app restarts
"""
import json
import os
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict, Any
class SessionStore:
"""Manages persistent storage of conversation sessions"""
def __init__(self, storage_dir: str = "sessions"):
self.storage_dir = Path(storage_dir)
self.storage_dir.mkdir(parents=True, exist_ok=True)
def save_session(self, user_id: str, session_data: Dict[str, Any]) -> None:
"""
Save user session to disk
Args:
user_id: Unique user identifier
session_data: Session data to save (memory state)
"""
session_file = self.storage_dir / f"{user_id}.json"
# Add metadata
session_data['last_updated'] = datetime.now().isoformat()
session_data['user_id'] = user_id
with open(session_file, 'w', encoding='utf-8') as f:
json.dump(session_data, f, ensure_ascii=False, indent=2)
def load_session(self, user_id: str) -> Optional[Dict[str, Any]]:
"""
Load user session from disk
Args:
user_id: Unique user identifier
Returns:
Session data or None if not found
"""
session_file = self.storage_dir / f"{user_id}.json"
if not session_file.exists():
return None
try:
with open(session_file, 'r', encoding='utf-8') as f:
return json.load(f)
except (json.JSONDecodeError, IOError) as e:
print(f"⚠️ Error loading session for {user_id}: {e}")
return None
def delete_session(self, user_id: str) -> bool:
"""
Delete user session
Args:
user_id: Unique user identifier
Returns:
True if deleted, False if not found
"""
session_file = self.storage_dir / f"{user_id}.json"
if session_file.exists():
session_file.unlink()
return True
return False
def list_sessions(self) -> list:
"""
List all stored sessions
Returns:
List of user IDs with sessions
"""
return [f.stem for f in self.storage_dir.glob("*.json")]
def get_session_info(self, user_id: str) -> Optional[Dict[str, Any]]:
"""
Get session metadata without loading full data
Args:
user_id: Unique user identifier
Returns:
Session metadata or None
"""
session_file = self.storage_dir / f"{user_id}.json"
if not session_file.exists():
return None
try:
with open(session_file, 'r', encoding='utf-8') as f:
data = json.load(f)
return {
'user_id': data.get('user_id'),
'last_updated': data.get('last_updated'),
'has_profile': bool(data.get('user_profile')),
'current_agent': data.get('current_agent'),
'conversation_count': len(data.get('conversation_history', []))
}
except (json.JSONDecodeError, IOError):
return None
def cleanup_old_sessions(self, days: int = 30) -> int:
"""
Delete sessions older than specified days
Args:
days: Number of days to keep sessions
Returns:
Number of sessions deleted
"""
from datetime import timedelta
cutoff_date = datetime.now() - timedelta(days=days)
deleted_count = 0
for session_file in self.storage_dir.glob("*.json"):
try:
with open(session_file, 'r', encoding='utf-8') as f:
data = json.load(f)
last_updated = datetime.fromisoformat(data.get('last_updated', ''))
if last_updated < cutoff_date:
session_file.unlink()
deleted_count += 1
except (json.JSONDecodeError, IOError, ValueError):
continue
return deleted_count
# Global instance
_session_store = None
def get_session_store() -> SessionStore:
"""Get global session store instance"""
global _session_store
if _session_store is None:
_session_store = SessionStore()
return _session_store