feat(tasks): T55-T58 implement background tasks for OpenRouter sync
- T55: Setup APScheduler with AsyncIOScheduler and @scheduled_job decorator - T56: Implement hourly usage stats sync from OpenRouter API - T57: Implement daily API key validation job - T58: Implement weekly cleanup job for old usage stats - Add usage_stats_retention_days config option - Integrate scheduler with FastAPI lifespan events - Add 26 unit tests for scheduler, sync, and cleanup tasks - Add apscheduler to requirements.txt The background tasks now automatically: - Sync usage stats every hour from OpenRouter - Validate API keys daily at 2 AM UTC - Clean up old data weekly on Sunday at 3 AM UTC
This commit is contained in:
59
src/openrouter_monitor/tasks/cleanup.py
Normal file
59
src/openrouter_monitor/tasks/cleanup.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""Cleanup tasks for old data.
|
||||
|
||||
T58: Task to clean up old usage stats data.
|
||||
"""
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from sqlalchemy import delete
|
||||
|
||||
from openrouter_monitor.database import SessionLocal
|
||||
from openrouter_monitor.models.usage_stats import UsageStats
|
||||
from openrouter_monitor.config import get_settings
|
||||
from openrouter_monitor.tasks.scheduler import scheduled_job
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
settings = get_settings()
|
||||
|
||||
|
||||
@scheduled_job(
|
||||
CronTrigger(day_of_week='sun', hour=3, minute=0),
|
||||
id='cleanup_old_usage_stats',
|
||||
replace_existing=True
|
||||
)
|
||||
async def cleanup_old_usage_stats():
|
||||
"""Clean up usage stats older than retention period.
|
||||
|
||||
Runs weekly on Sunday at 3:00 AM UTC.
|
||||
Removes UsageStats records older than usage_stats_retention_days
|
||||
(default: 365 days).
|
||||
|
||||
The retention period is configurable via the
|
||||
USAGE_STATS_RETENTION_DAYS environment variable.
|
||||
"""
|
||||
logger.info("Starting cleanup of old usage stats")
|
||||
|
||||
try:
|
||||
with SessionLocal() as db:
|
||||
# Calculate cutoff date
|
||||
retention_days = settings.usage_stats_retention_days
|
||||
cutoff_date = datetime.utcnow().date() - timedelta(days=retention_days)
|
||||
|
||||
logger.info(f"Removing usage stats older than {cutoff_date}")
|
||||
|
||||
# Delete old records
|
||||
stmt = delete(UsageStats).where(UsageStats.date < cutoff_date)
|
||||
result = db.execute(stmt)
|
||||
deleted_count = result.rowcount
|
||||
|
||||
db.commit()
|
||||
|
||||
logger.info(
|
||||
f"Cleanup completed. Deleted {deleted_count} old usage stats records "
|
||||
f"(retention: {retention_days} days)"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in cleanup_old_usage_stats job: {e}")
|
||||
Reference in New Issue
Block a user