fix test and add doc
This commit is contained in:
@@ -13,10 +13,10 @@ from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import psutil
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.server.database.models import Download, DownloadStatus
|
||||
from src.server.database.models import DownloadQueueItem, DownloadStatus
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -124,8 +124,8 @@ class AnalyticsService:
|
||||
cutoff_date = datetime.now() - timedelta(days=days)
|
||||
|
||||
# Query downloads within period
|
||||
stmt = select(Download).where(
|
||||
Download.created_at >= cutoff_date
|
||||
stmt = select(DownloadQueueItem).where(
|
||||
DownloadQueueItem.created_at >= cutoff_date
|
||||
)
|
||||
result = await db.execute(stmt)
|
||||
downloads = result.scalars().all()
|
||||
@@ -138,16 +138,16 @@ class AnalyticsService:
|
||||
failed = [d for d in downloads
|
||||
if d.status == DownloadStatus.FAILED]
|
||||
|
||||
total_bytes = sum(d.size_bytes or 0 for d in successful)
|
||||
total_seconds = sum(
|
||||
d.duration_seconds or 0 for d in successful
|
||||
) or 1
|
||||
|
||||
avg_speed = (
|
||||
(total_bytes / (1024 * 1024)) / total_seconds
|
||||
if total_seconds > 0
|
||||
total_bytes = sum(d.total_bytes or 0 for d in successful)
|
||||
avg_speed_list = [
|
||||
d.download_speed or 0.0 for d in successful if d.download_speed
|
||||
]
|
||||
avg_speed_mbps = (
|
||||
sum(avg_speed_list) / len(avg_speed_list) / (1024 * 1024)
|
||||
if avg_speed_list
|
||||
else 0.0
|
||||
)
|
||||
|
||||
success_rate = (
|
||||
len(successful) / len(downloads) * 100 if downloads else 0.0
|
||||
)
|
||||
@@ -157,11 +157,9 @@ class AnalyticsService:
|
||||
successful_downloads=len(successful),
|
||||
failed_downloads=len(failed),
|
||||
total_bytes_downloaded=total_bytes,
|
||||
average_speed_mbps=avg_speed,
|
||||
average_speed_mbps=avg_speed_mbps,
|
||||
success_rate=success_rate,
|
||||
average_duration_seconds=total_seconds / len(successful)
|
||||
if successful
|
||||
else 0.0,
|
||||
average_duration_seconds=0.0, # Not available in model
|
||||
)
|
||||
|
||||
async def get_series_popularity(
|
||||
@@ -176,39 +174,42 @@ class AnalyticsService:
|
||||
Returns:
|
||||
List of SeriesPopularity objects
|
||||
"""
|
||||
stmt = (
|
||||
select(
|
||||
Download.series_name,
|
||||
func.count(Download.id).label("download_count"),
|
||||
func.sum(Download.size_bytes).label("total_size"),
|
||||
func.max(Download.created_at).label("last_download"),
|
||||
func.countif(
|
||||
Download.status == DownloadStatus.COMPLETED
|
||||
).label("successful"),
|
||||
)
|
||||
.group_by(Download.series_name)
|
||||
.order_by(func.count(Download.id).desc())
|
||||
.limit(limit)
|
||||
)
|
||||
# Use raw SQL approach since we need to group and join
|
||||
from sqlalchemy import text
|
||||
|
||||
result = await db.execute(stmt)
|
||||
query = text("""
|
||||
SELECT
|
||||
s.title as series_name,
|
||||
COUNT(d.id) as download_count,
|
||||
SUM(d.total_bytes) as total_size,
|
||||
MAX(d.created_at) as last_download,
|
||||
SUM(CASE WHEN d.status = 'COMPLETED'
|
||||
THEN 1 ELSE 0 END) as successful
|
||||
FROM download_queue d
|
||||
JOIN anime_series s ON d.series_id = s.id
|
||||
GROUP BY s.id, s.title
|
||||
ORDER BY download_count DESC
|
||||
LIMIT :limit
|
||||
""")
|
||||
|
||||
result = await db.execute(query, {"limit": limit})
|
||||
rows = result.all()
|
||||
|
||||
popularity = []
|
||||
for row in rows:
|
||||
success_rate = 0.0
|
||||
if row.download_count > 0:
|
||||
success_rate = (
|
||||
(row.successful or 0) / row.download_count * 100
|
||||
)
|
||||
download_count = row[1] or 0
|
||||
if download_count > 0:
|
||||
successful = row[4] or 0
|
||||
success_rate = (successful / download_count * 100)
|
||||
|
||||
popularity.append(
|
||||
SeriesPopularity(
|
||||
series_name=row.series_name or "Unknown",
|
||||
download_count=row.download_count or 0,
|
||||
total_size_bytes=row.total_size or 0,
|
||||
last_download=row.last_download.isoformat()
|
||||
if row.last_download
|
||||
series_name=row[0] or "Unknown",
|
||||
download_count=download_count,
|
||||
total_size_bytes=row[2] or 0,
|
||||
last_download=row[3].isoformat()
|
||||
if row[3]
|
||||
else None,
|
||||
success_rate=success_rate,
|
||||
)
|
||||
@@ -288,8 +289,8 @@ class AnalyticsService:
|
||||
cutoff_time = datetime.now() - timedelta(hours=hours)
|
||||
|
||||
# Get download metrics
|
||||
stmt = select(Download).where(
|
||||
Download.created_at >= cutoff_time
|
||||
stmt = select(DownloadQueueItem).where(
|
||||
DownloadQueueItem.created_at >= cutoff_time
|
||||
)
|
||||
result = await db.execute(stmt)
|
||||
downloads = result.scalars().all()
|
||||
|
||||
Reference in New Issue
Block a user