Dateien
Hetzner-Backup/v2_lizenzserver/app/core/scheduler.py
2025-07-03 20:38:33 +00:00

116 Zeilen
3.6 KiB
Python

"""
Background scheduler for License Server
Handles periodic tasks like session cleanup
"""
import logging
from datetime import datetime, timedelta
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger
from sqlalchemy import text
from sqlalchemy.orm import Session
from app.db.database import SessionLocal
logger = logging.getLogger(__name__)
scheduler = BackgroundScheduler()
def cleanup_expired_sessions():
"""Clean up sessions that haven't sent heartbeat within timeout period"""
db: Session = SessionLocal()
try:
# Get session timeout from config (default 60 seconds)
result = db.execute(text("""
SELECT session_timeout
FROM client_configs
WHERE client_name = 'Account Forger'
""")).first()
timeout_seconds = result[0] if result else 60
# Find expired sessions
expired_sessions = db.execute(text(f"""
SELECT id, license_id, hardware_fingerprint, session_token
FROM license_sessions
WHERE ended_at IS NULL
AND last_heartbeat < NOW() - INTERVAL '{timeout_seconds} seconds'
""")).fetchall()
if expired_sessions:
logger.info(f"Found {len(expired_sessions)} expired sessions to clean up")
# Mark sessions as ended
for session in expired_sessions:
db.execute(text("""
UPDATE license_sessions
SET ended_at = NOW(), end_reason = 'timeout'
WHERE id = :session_id
"""), {"session_id": session[0]})
logger.info(f"Ended session {session[0]} for license {session[1]} due to timeout")
db.commit()
logger.info(f"Successfully cleaned up {len(expired_sessions)} expired sessions")
except Exception as e:
logger.error(f"Error cleaning up sessions: {str(e)}")
db.rollback()
finally:
db.close()
def cleanup_old_sessions():
"""Remove old ended sessions from database (older than 30 days)"""
db: Session = SessionLocal()
try:
result = db.execute(text("""
DELETE FROM license_sessions
WHERE ended_at IS NOT NULL
AND ended_at < NOW() - INTERVAL '30 days'
"""))
if result.rowcount > 0:
db.commit()
logger.info(f"Cleaned up {result.rowcount} old sessions")
except Exception as e:
logger.error(f"Error cleaning up old sessions: {str(e)}")
db.rollback()
finally:
db.close()
def init_scheduler():
"""Initialize and start the background scheduler"""
# Add job to cleanup expired sessions every 30 seconds
scheduler.add_job(
func=cleanup_expired_sessions,
trigger=IntervalTrigger(seconds=30),
id='cleanup_expired_sessions',
name='Cleanup expired sessions',
replace_existing=True
)
# Add job to cleanup old sessions daily at 3 AM
scheduler.add_job(
func=cleanup_old_sessions,
trigger='cron',
hour=3,
minute=0,
id='cleanup_old_sessions',
name='Cleanup old sessions',
replace_existing=True
)
scheduler.start()
logger.info("Background scheduler started")
logger.info("- Session cleanup runs every 30 seconds")
logger.info("- Old session cleanup runs daily at 3:00 AM")
def shutdown_scheduler():
"""Shutdown the scheduler gracefully"""
if scheduler.running:
scheduler.shutdown()
logger.info("Background scheduler stopped")