PyRunner / core /services /dashboard_service.py
Akoda35's picture
Upload 15 files
56b2689 verified
Raw
History Blame Contribute Delete
4.05 kB
"""
Dashboard service for gathering statistics and widgets data.
"""
from datetime import timedelta
from typing import Optional
from django.db.models import QuerySet
from django.utils import timezone
class DashboardService:
"""Service for gathering dashboard statistics and widget data."""
@classmethod
def get_statistics(cls) -> dict:
"""
Get all dashboard statistics.
Returns dict with:
- total_scripts: Total number of scripts
- active_scripts: Scripts with is_enabled=True
- runs_today: Runs created today
- runs_this_week: Runs created in last 7 days
- success_rate: Percentage of successful runs (or None if no runs)
- queue_size: Number of tasks in queue
"""
from django_q.models import OrmQ
from core.models import Run, Script
now = timezone.now()
today = now.date()
week_ago = now - timedelta(days=7)
# Script counts
total_scripts = Script.objects.count()
active_scripts = Script.objects.filter(is_enabled=True).count()
# Run counts
total_runs = Run.objects.count()
runs_today = Run.objects.filter(created_at__date=today).count()
runs_this_week = Run.objects.filter(created_at__gte=week_ago).count()
# Success rate
success_rate = None
if total_runs > 0:
success_count = Run.objects.filter(status=Run.Status.SUCCESS).count()
success_rate = round((success_count / total_runs) * 100, 1)
# Queue size
try:
queue_size = OrmQ.objects.count()
except Exception:
queue_size = 0
return {
"total_scripts": total_scripts,
"active_scripts": active_scripts,
"runs_today": runs_today,
"runs_this_week": runs_this_week,
"success_rate": success_rate,
"queue_size": queue_size,
}
@classmethod
def get_recent_failures(cls, limit: int = 5) -> QuerySet:
"""
Get recent failed and timeout runs.
Args:
limit: Maximum number of runs to return
Returns:
QuerySet of Run objects ordered by most recent
"""
from core.models import Run
return (
Run.objects.filter(status__in=[Run.Status.FAILED, Run.Status.TIMEOUT])
.select_related("script")
.order_by("-created_at")[:limit]
)
@classmethod
def get_upcoming_scheduled_runs(cls, limit: int = 5) -> QuerySet:
"""
Get upcoming scheduled script runs.
Args:
limit: Maximum number of schedules to return
Returns:
QuerySet of ScriptSchedule objects with upcoming runs
"""
from core.models import ScriptSchedule
now = timezone.now()
return (
ScriptSchedule.objects.filter(
next_run__isnull=False,
next_run__gt=now,
is_active=True,
run_mode__in=[ScriptSchedule.RunMode.INTERVAL, ScriptSchedule.RunMode.DAILY],
)
.select_related("script")
.order_by("next_run")[:limit]
)
@classmethod
def get_system_health(cls) -> dict:
"""
Get system health status.
Returns dict with:
- worker_status: str ("running", "stopped", "unknown")
- worker_status_text: str (human-readable)
- schedules_paused: bool
- queue_size: int
"""
from core.models import GlobalSettings
from core.services.system_info_service import SystemInfoService
worker_info = SystemInfoService.get_worker_status()
global_settings = GlobalSettings.get_settings()
return {
"worker_status": worker_info["status"],
"worker_status_text": worker_info["status_text"],
"schedules_paused": global_settings.schedules_paused,
"queue_size": worker_info["queued_tasks"],
}