mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2026-03-18 19:26:31 +01:00
refactor: backend standardization (service layer, validation, route splitting) + image cache and Scryfall API fixes
This commit is contained in:
parent
e81b47bccf
commit
f784741416
35 changed files with 7054 additions and 4344 deletions
|
|
@ -4,45 +4,194 @@ import time
|
|||
import uuid
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
# Extremely simple in-memory session/task store for MVP
|
||||
_SESSIONS: Dict[str, Dict[str, Any]] = {}
|
||||
_TTL_SECONDS = 60 * 60 * 8 # 8 hours
|
||||
from .base import StateService
|
||||
from .interfaces import SessionService
|
||||
|
||||
|
||||
# Session TTL: 8 hours
|
||||
SESSION_TTL_SECONDS = 60 * 60 * 8
|
||||
|
||||
|
||||
class SessionManager(StateService):
|
||||
"""Session management service.
|
||||
|
||||
Manages user sessions with automatic TTL-based cleanup.
|
||||
Thread-safe with in-memory storage.
|
||||
"""
|
||||
|
||||
def __init__(self, ttl_seconds: int = SESSION_TTL_SECONDS) -> None:
|
||||
"""Initialize session manager.
|
||||
|
||||
Args:
|
||||
ttl_seconds: Session time-to-live in seconds
|
||||
"""
|
||||
super().__init__()
|
||||
self._ttl_seconds = ttl_seconds
|
||||
|
||||
def new_session_id(self) -> str:
|
||||
"""Create a new session ID.
|
||||
|
||||
Returns:
|
||||
Unique session identifier
|
||||
"""
|
||||
return uuid.uuid4().hex
|
||||
|
||||
def touch_session(self, session_id: str) -> Dict[str, Any]:
|
||||
"""Update session last access time.
|
||||
|
||||
Args:
|
||||
session_id: Session identifier
|
||||
|
||||
Returns:
|
||||
Session state dictionary
|
||||
"""
|
||||
now = time.time()
|
||||
state = self.get_state(session_id)
|
||||
state["updated"] = now
|
||||
return state
|
||||
|
||||
def get_session(self, session_id: Optional[str]) -> Dict[str, Any]:
|
||||
"""Get or create session state.
|
||||
|
||||
Args:
|
||||
session_id: Session identifier (creates new if None)
|
||||
|
||||
Returns:
|
||||
Session state dictionary
|
||||
"""
|
||||
if not session_id:
|
||||
session_id = self.new_session_id()
|
||||
return self.touch_session(session_id)
|
||||
|
||||
def set_value(self, session_id: str, key: str, value: Any) -> None:
|
||||
"""Set a value in session state.
|
||||
|
||||
Args:
|
||||
session_id: Session identifier
|
||||
key: State key
|
||||
value: Value to store
|
||||
"""
|
||||
self.touch_session(session_id)[key] = value
|
||||
|
||||
def get_value(self, session_id: str, key: str, default: Any = None) -> Any:
|
||||
"""Get a value from session state.
|
||||
|
||||
Args:
|
||||
session_id: Session identifier
|
||||
key: State key
|
||||
default: Default value if key not found
|
||||
|
||||
Returns:
|
||||
Stored value or default
|
||||
"""
|
||||
return self.touch_session(session_id).get(key, default)
|
||||
|
||||
def _initialize_state(self, key: str) -> Dict[str, Any]:
|
||||
"""Initialize state for a new session.
|
||||
|
||||
Args:
|
||||
key: Session ID
|
||||
|
||||
Returns:
|
||||
Initial session state
|
||||
"""
|
||||
now = time.time()
|
||||
return {"created": now, "updated": now}
|
||||
|
||||
def _should_cleanup(self, key: str, state: Dict[str, Any]) -> bool:
|
||||
"""Check if session should be cleaned up.
|
||||
|
||||
Args:
|
||||
key: Session ID
|
||||
state: Session state
|
||||
|
||||
Returns:
|
||||
True if session is expired
|
||||
"""
|
||||
now = time.time()
|
||||
updated = state.get("updated", 0)
|
||||
return (now - updated) > self._ttl_seconds
|
||||
|
||||
|
||||
# Global session manager instance
|
||||
_session_manager: Optional[SessionManager] = None
|
||||
|
||||
|
||||
def _get_manager() -> SessionManager:
|
||||
"""Get or create global session manager instance.
|
||||
|
||||
Returns:
|
||||
SessionManager instance
|
||||
"""
|
||||
global _session_manager
|
||||
if _session_manager is None:
|
||||
_session_manager = SessionManager()
|
||||
return _session_manager
|
||||
|
||||
|
||||
# Backward-compatible function API
|
||||
def new_sid() -> str:
|
||||
return uuid.uuid4().hex
|
||||
"""Create a new session ID.
|
||||
|
||||
Returns:
|
||||
Unique session identifier
|
||||
"""
|
||||
return _get_manager().new_session_id()
|
||||
|
||||
|
||||
def touch_session(sid: str) -> Dict[str, Any]:
|
||||
now = time.time()
|
||||
s = _SESSIONS.get(sid)
|
||||
if not s:
|
||||
s = {"created": now, "updated": now}
|
||||
_SESSIONS[sid] = s
|
||||
else:
|
||||
s["updated"] = now
|
||||
return s
|
||||
"""Update session last access time.
|
||||
|
||||
Args:
|
||||
sid: Session identifier
|
||||
|
||||
Returns:
|
||||
Session state dictionary
|
||||
"""
|
||||
return _get_manager().touch_session(sid)
|
||||
|
||||
|
||||
def get_session(sid: Optional[str]) -> Dict[str, Any]:
|
||||
if not sid:
|
||||
sid = new_sid()
|
||||
return touch_session(sid)
|
||||
"""Get or create session state.
|
||||
|
||||
Args:
|
||||
sid: Session identifier (creates new if None)
|
||||
|
||||
Returns:
|
||||
Session state dictionary
|
||||
"""
|
||||
return _get_manager().get_session(sid)
|
||||
|
||||
|
||||
def set_session_value(sid: str, key: str, value: Any) -> None:
|
||||
touch_session(sid)[key] = value
|
||||
"""Set a value in session state.
|
||||
|
||||
Args:
|
||||
sid: Session identifier
|
||||
key: State key
|
||||
value: Value to store
|
||||
"""
|
||||
_get_manager().set_value(sid, key, value)
|
||||
|
||||
|
||||
def get_session_value(sid: str, key: str, default: Any = None) -> Any:
|
||||
return touch_session(sid).get(key, default)
|
||||
"""Get a value from session state.
|
||||
|
||||
Args:
|
||||
sid: Session identifier
|
||||
key: State key
|
||||
default: Default value if key not found
|
||||
|
||||
Returns:
|
||||
Stored value or default
|
||||
"""
|
||||
return _get_manager().get_value(sid, key, default)
|
||||
|
||||
|
||||
def cleanup_expired() -> None:
|
||||
now = time.time()
|
||||
expired = [sid for sid, s in _SESSIONS.items() if now - s.get("updated", 0) > _TTL_SECONDS]
|
||||
for sid in expired:
|
||||
try:
|
||||
del _SESSIONS[sid]
|
||||
except Exception:
|
||||
pass
|
||||
def cleanup_expired() -> int:
|
||||
"""Clean up expired sessions.
|
||||
|
||||
Returns:
|
||||
Number of sessions cleaned up
|
||||
"""
|
||||
return _get_manager().cleanup_state()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue