Get session query handler.
Retrieves a single session by ID with authorization check.
Uses cache-first strategy for performance.
Classes
GetSessionError
Get session error reasons.
Source code in src/application/queries/handlers/get_session_handler.py
| class GetSessionError:
"""Get session error reasons."""
SESSION_NOT_FOUND = "session_not_found"
NOT_OWNER = "not_session_owner"
|
SessionResult
dataclass
Session query result.
Source code in src/application/queries/handlers/get_session_handler.py
| @dataclass
class SessionResult:
"""Session query result."""
id: UUID
user_id: UUID
device_info: str | None
ip_address: str | None
location: str | None
created_at: datetime | None
last_activity_at: datetime | None
expires_at: datetime | None
is_revoked: bool
is_current: bool = False
|
GetSessionHandler
Handler for getting a single session.
Uses cache-first strategy:
1. Try cache
2. Fall back to database
3. Populate cache on miss
Source code in src/application/queries/handlers/get_session_handler.py
| class GetSessionHandler:
"""Handler for getting a single session.
Uses cache-first strategy:
1. Try cache
2. Fall back to database
3. Populate cache on miss
"""
def __init__(
self,
session_repo: SessionRepository,
session_cache: SessionCache,
) -> None:
"""Initialize handler with dependencies.
Args:
session_repo: Session repository for persistence.
session_cache: Session cache for fast lookups.
"""
self._session_repo = session_repo
self._session_cache = session_cache
async def handle(self, query: GetSession) -> Result[SessionResult, str]:
"""Handle get session query.
Args:
query: GetSession query with session_id and user_id.
Returns:
Success(SessionResult) with session data.
Failure(error_message) if not found or not owner.
"""
# Step 1: Try cache first
session = await self._session_cache.get(query.session_id)
# Step 2: Fall back to database
if session is None:
session = await self._session_repo.find_by_id(query.session_id)
# Populate cache on miss (if found and not revoked)
if session is not None and not session.is_revoked:
await self._session_cache.set(session)
# Step 3: Check found
if session is None:
return Failure(error=GetSessionError.SESSION_NOT_FOUND)
# Step 4: Check ownership
if session.user_id != query.user_id:
return Failure(error=GetSessionError.NOT_OWNER)
# Step 5: Return result
return Success(
value=SessionResult(
id=session.id,
user_id=session.user_id,
device_info=session.device_info,
ip_address=session.ip_address,
location=session.location,
created_at=session.created_at,
last_activity_at=session.last_activity_at,
expires_at=session.expires_at,
is_revoked=session.is_revoked,
is_current=False, # Caller sets this
)
)
|
Functions
__init__
__init__(
session_repo: SessionRepository,
session_cache: SessionCache,
) -> None
Parameters:
| Name |
Type |
Description |
Default |
session_repo
|
SessionRepository
|
Session repository for persistence.
|
required
|
session_cache
|
SessionCache
|
Session cache for fast lookups.
|
required
|
Source code in src/application/queries/handlers/get_session_handler.py
| def __init__(
self,
session_repo: SessionRepository,
session_cache: SessionCache,
) -> None:
"""Initialize handler with dependencies.
Args:
session_repo: Session repository for persistence.
session_cache: Session cache for fast lookups.
"""
self._session_repo = session_repo
self._session_cache = session_cache
|
handle
async
handle(query: GetSession) -> Result[SessionResult, str]
Handle get session query.
Parameters:
| Name |
Type |
Description |
Default |
query
|
GetSession
|
GetSession query with session_id and user_id.
|
required
|
Returns:
| Type |
Description |
Result[SessionResult, str]
|
Success(SessionResult) with session data.
|
Result[SessionResult, str]
|
Failure(error_message) if not found or not owner.
|
Source code in src/application/queries/handlers/get_session_handler.py
| async def handle(self, query: GetSession) -> Result[SessionResult, str]:
"""Handle get session query.
Args:
query: GetSession query with session_id and user_id.
Returns:
Success(SessionResult) with session data.
Failure(error_message) if not found or not owner.
"""
# Step 1: Try cache first
session = await self._session_cache.get(query.session_id)
# Step 2: Fall back to database
if session is None:
session = await self._session_repo.find_by_id(query.session_id)
# Populate cache on miss (if found and not revoked)
if session is not None and not session.is_revoked:
await self._session_cache.set(session)
# Step 3: Check found
if session is None:
return Failure(error=GetSessionError.SESSION_NOT_FOUND)
# Step 4: Check ownership
if session.user_id != query.user_id:
return Failure(error=GetSessionError.NOT_OWNER)
# Step 5: Return result
return Success(
value=SessionResult(
id=session.id,
user_id=session.user_id,
device_info=session.device_info,
ip_address=session.ip_address,
location=session.location,
created_at=session.created_at,
last_activity_at=session.last_activity_at,
expires_at=session.expires_at,
is_revoked=session.is_revoked,
is_current=False, # Caller sets this
)
)
|