refactor: Improve exception handling and logging in authentication and playlist services; enhance code readability and structure
All checks were successful
Backend CI / lint (push) Successful in 9m21s
Backend CI / test (push) Successful in 4m18s

This commit is contained in:
JSC
2025-08-13 00:04:55 +02:00
parent f094fbf140
commit bee1076239
14 changed files with 144 additions and 66 deletions

View File

@@ -132,7 +132,9 @@ class PlaylistRepository(BaseRepository[Playlist]):
result = await self.session.exec(statement)
return list(result.all())
except Exception:
logger.exception("Failed to get playlist sound entries for playlist: %s", playlist_id)
logger.exception(
"Failed to get playlist sound entries for playlist: %s", playlist_id,
)
raise
async def add_sound_to_playlist(
@@ -302,19 +304,22 @@ class PlaylistRepository(BaseRepository[Playlist]):
)
raise
async def search_and_sort(
async def search_and_sort( # noqa: C901, PLR0913, PLR0912, PLR0915
self,
search_query: str | None = None,
sort_by: PlaylistSortField | None = None,
sort_order: SortOrder = SortOrder.ASC,
user_id: int | None = None,
include_stats: bool = False,
include_stats: bool = False, # noqa: FBT001, FBT002
limit: int | None = None,
offset: int = 0,
) -> list[dict]:
"""Search and sort playlists with optional statistics."""
try:
if include_stats and sort_by in (PlaylistSortField.SOUND_COUNT, PlaylistSortField.TOTAL_DURATION):
if include_stats and sort_by in (
PlaylistSortField.SOUND_COUNT,
PlaylistSortField.TOTAL_DURATION,
):
# Use subquery for sorting by stats
subquery = (
select(
@@ -329,12 +334,18 @@ class PlaylistRepository(BaseRepository[Playlist]):
Playlist.created_at,
Playlist.updated_at,
func.count(PlaylistSound.id).label("sound_count"),
func.coalesce(func.sum(Sound.duration), 0).label("total_duration"),
func.coalesce(func.sum(Sound.duration), 0).label(
"total_duration",
),
User.name.label("user_name"),
)
.select_from(Playlist)
.join(User, Playlist.user_id == User.id, isouter=True)
.join(PlaylistSound, Playlist.id == PlaylistSound.playlist_id, isouter=True)
.join(
PlaylistSound,
Playlist.id == PlaylistSound.playlist_id,
isouter=True,
)
.join(Sound, PlaylistSound.sound_id == Sound.id, isouter=True)
.group_by(Playlist.id, User.name)
)
@@ -342,7 +353,9 @@ class PlaylistRepository(BaseRepository[Playlist]):
# Apply filters
if search_query and search_query.strip():
search_pattern = f"%{search_query.strip().lower()}%"
subquery = subquery.where(func.lower(Playlist.name).like(search_pattern))
subquery = subquery.where(
func.lower(Playlist.name).like(search_pattern),
)
if user_id is not None:
subquery = subquery.where(Playlist.user_id == user_id)
@@ -350,14 +363,20 @@ class PlaylistRepository(BaseRepository[Playlist]):
# Apply sorting
if sort_by == PlaylistSortField.SOUND_COUNT:
if sort_order == SortOrder.DESC:
subquery = subquery.order_by(func.count(PlaylistSound.id).desc())
subquery = subquery.order_by(
func.count(PlaylistSound.id).desc(),
)
else:
subquery = subquery.order_by(func.count(PlaylistSound.id).asc())
elif sort_by == PlaylistSortField.TOTAL_DURATION:
if sort_order == SortOrder.DESC:
subquery = subquery.order_by(func.coalesce(func.sum(Sound.duration), 0).desc())
subquery = subquery.order_by(
func.coalesce(func.sum(Sound.duration), 0).desc(),
)
else:
subquery = subquery.order_by(func.coalesce(func.sum(Sound.duration), 0).asc())
subquery = subquery.order_by(
func.coalesce(func.sum(Sound.duration), 0).asc(),
)
else:
# Default sorting by name
subquery = subquery.order_by(Playlist.name.asc())
@@ -377,12 +396,18 @@ class PlaylistRepository(BaseRepository[Playlist]):
Playlist.created_at,
Playlist.updated_at,
func.count(PlaylistSound.id).label("sound_count"),
func.coalesce(func.sum(Sound.duration), 0).label("total_duration"),
func.coalesce(func.sum(Sound.duration), 0).label(
"total_duration",
),
User.name.label("user_name"),
)
.select_from(Playlist)
.join(User, Playlist.user_id == User.id, isouter=True)
.join(PlaylistSound, Playlist.id == PlaylistSound.playlist_id, isouter=True)
.join(
PlaylistSound,
Playlist.id == PlaylistSound.playlist_id,
isouter=True,
)
.join(Sound, PlaylistSound.sound_id == Sound.id, isouter=True)
.group_by(Playlist.id, User.name)
)
@@ -390,7 +415,9 @@ class PlaylistRepository(BaseRepository[Playlist]):
# Apply filters
if search_query and search_query.strip():
search_pattern = f"%{search_query.strip().lower()}%"
subquery = subquery.where(func.lower(Playlist.name).like(search_pattern))
subquery = subquery.where(
func.lower(Playlist.name).like(search_pattern),
)
if user_id is not None:
subquery = subquery.where(Playlist.user_id == user_id)
@@ -426,9 +453,8 @@ class PlaylistRepository(BaseRepository[Playlist]):
rows = result.all()
# Convert to dictionary format
playlists = []
for row in rows:
playlists.append({
playlists = [
{
"id": row.id,
"name": row.name,
"description": row.description,
@@ -442,12 +468,20 @@ class PlaylistRepository(BaseRepository[Playlist]):
"updated_at": row.updated_at,
"sound_count": row.sound_count or 0,
"total_duration": row.total_duration or 0,
})
}
for row in rows
]
return playlists
except Exception:
logger.exception(
"Failed to search and sort playlists: query=%s, sort_by=%s, sort_order=%s",
search_query, sort_by, sort_order,
(
"Failed to search and sort playlists: "
"query=%s, sort_by=%s, sort_order=%s"
),
search_query,
sort_by,
sort_order,
)
raise
else:
return playlists

View File

@@ -132,7 +132,7 @@ class SoundRepository(BaseRepository[Sound]):
logger.exception("Failed to get sounds by types: %s", sound_types)
raise
async def search_and_sort(
async def search_and_sort( # noqa: PLR0913
self,
search_query: str | None = None,
sound_types: list[str] | None = None,
@@ -177,8 +177,14 @@ class SoundRepository(BaseRepository[Sound]):
return list(result.all())
except Exception:
logger.exception(
"Failed to search and sort sounds: query=%s, types=%s, sort_by=%s, sort_order=%s",
search_query, sound_types, sort_by, sort_order,
(
"Failed to search and sort sounds: "
"query=%s, types=%s, sort_by=%s, sort_order=%s"
),
search_query,
sound_types,
sort_by,
sort_order,
)
raise
@@ -189,21 +195,26 @@ class SoundRepository(BaseRepository[Sound]):
func.count(Sound.id).label("count"),
func.sum(Sound.play_count).label("total_plays"),
func.sum(Sound.duration).label("total_duration"),
func.sum(Sound.size + func.coalesce(Sound.normalized_size, 0)).label("total_size"),
func.sum(
Sound.size + func.coalesce(Sound.normalized_size, 0),
).label("total_size"),
).where(Sound.type == "SDB")
result = await self.session.exec(statement)
row = result.first()
return {
"count": row.count if row.count is not None else 0,
"total_plays": row.total_plays if row.total_plays is not None else 0,
"total_duration": row.total_duration if row.total_duration is not None else 0,
"total_size": row.total_size if row.total_size is not None else 0,
}
except Exception:
logger.exception("Failed to get soundboard statistics")
raise
else:
return {
"count": row.count if row.count is not None else 0,
"total_plays": row.total_plays if row.total_plays is not None else 0,
"total_duration": (
row.total_duration if row.total_duration is not None else 0
),
"total_size": row.total_size if row.total_size is not None else 0,
}
async def get_track_statistics(self) -> dict[str, int | float]:
"""Get statistics for EXT type sounds."""
@@ -212,21 +223,26 @@ class SoundRepository(BaseRepository[Sound]):
func.count(Sound.id).label("count"),
func.sum(Sound.play_count).label("total_plays"),
func.sum(Sound.duration).label("total_duration"),
func.sum(Sound.size + func.coalesce(Sound.normalized_size, 0)).label("total_size"),
func.sum(
Sound.size + func.coalesce(Sound.normalized_size, 0),
).label("total_size"),
).where(Sound.type == "EXT")
result = await self.session.exec(statement)
row = result.first()
return {
"count": row.count if row.count is not None else 0,
"total_plays": row.total_plays if row.total_plays is not None else 0,
"total_duration": row.total_duration if row.total_duration is not None else 0,
"total_size": row.total_size if row.total_size is not None else 0,
}
except Exception:
logger.exception("Failed to get track statistics")
raise
else:
return {
"count": row.count if row.count is not None else 0,
"total_plays": row.total_plays if row.total_plays is not None else 0,
"total_duration": (
row.total_duration if row.total_duration is not None else 0
),
"total_size": row.total_size if row.total_size is not None else 0,
}
async def get_top_sounds(
self,
@@ -234,7 +250,7 @@ class SoundRepository(BaseRepository[Sound]):
date_filter: datetime | None = None,
limit: int = 10,
) -> list[dict]:
"""Get top sounds by play count for a specific type and period using SoundPlayed records."""
"""Get top sounds by play count for a specific type and period."""
try:
# Join SoundPlayed with Sound and count plays within the period
statement = (