""" Scheduler module for handling background tasks """ import logging from apscheduler.schedulers.background import BackgroundScheduler import config from utils.backup import create_backup from db import get_connection def scheduled_backup(): """Führt ein geplantes Backup aus""" logging.info("Starte geplantes Backup...") create_backup(backup_type="scheduled", created_by="scheduler") def cleanup_expired_sessions(): """Clean up expired license sessions""" try: conn = get_connection() cur = conn.cursor() # Get client config for timeout value cur.execute(""" SELECT session_timeout FROM client_configs WHERE client_name = 'Account Forger' """) result = cur.fetchone() timeout_seconds = result[0] if result else 60 # Find expired sessions cur.execute(""" SELECT id, license_id, hardware_id, ip_address, client_version, started_at FROM license_sessions WHERE last_heartbeat < CURRENT_TIMESTAMP - INTERVAL '%s seconds' """, (timeout_seconds,)) expired_sessions = cur.fetchall() if expired_sessions: logging.info(f"Found {len(expired_sessions)} expired sessions to clean up") for session in expired_sessions: # Log to history cur.execute(""" INSERT INTO session_history (license_id, hardware_id, ip_address, client_version, started_at, ended_at, end_reason) VALUES (%s, %s, %s, %s, %s, CURRENT_TIMESTAMP, 'timeout') """, (session[1], session[2], session[3], session[4], session[5])) # Delete session cur.execute("DELETE FROM license_sessions WHERE id = %s", (session[0],)) conn.commit() logging.info(f"Cleaned up {len(expired_sessions)} expired sessions") cur.close() conn.close() except Exception as e: logging.error(f"Error cleaning up sessions: {str(e)}") if 'conn' in locals(): conn.rollback() def deactivate_expired_licenses(): """Deactivate licenses that have expired""" try: conn = get_connection() cur = conn.cursor() # Find active licenses that have expired # Check valid_until < today (at midnight) cur.execute(""" SELECT id, license_key, customer_id, valid_until FROM licenses WHERE is_active = true AND valid_until IS NOT NULL AND valid_until < CURRENT_DATE AND is_fake = false """) expired_licenses = cur.fetchall() if expired_licenses: logging.info(f"Found {len(expired_licenses)} expired licenses to deactivate") for license in expired_licenses: license_id, license_key, customer_id, valid_until = license # Deactivate the license cur.execute(""" UPDATE licenses SET is_active = false, updated_at = CURRENT_TIMESTAMP WHERE id = %s """, (license_id,)) # Log to audit trail cur.execute(""" INSERT INTO audit_log (timestamp, username, action, entity_type, entity_id, old_values, new_values, additional_info) VALUES (CURRENT_TIMESTAMP, 'system', 'DEACTIVATE', 'license', %s, jsonb_build_object('is_active', true), jsonb_build_object('is_active', false), %s) """, (license_id, f"License automatically deactivated due to expiration. Valid until: {valid_until}")) logging.info(f"Deactivated expired license: {license_key} (ID: {license_id})") conn.commit() logging.info(f"Successfully deactivated {len(expired_licenses)} expired licenses") else: logging.debug("No expired licenses found to deactivate") cur.close() conn.close() except Exception as e: logging.error(f"Error deactivating expired licenses: {str(e)}") if 'conn' in locals(): conn.rollback() def init_scheduler(): """Initialize and configure the scheduler""" scheduler = BackgroundScheduler() # Configure daily backup job scheduler.add_job( scheduled_backup, 'cron', hour=config.SCHEDULER_CONFIG['backup_hour'], minute=config.SCHEDULER_CONFIG['backup_minute'], id='daily_backup', replace_existing=True ) # Configure session cleanup job - runs every 60 seconds scheduler.add_job( cleanup_expired_sessions, 'interval', seconds=60, id='session_cleanup', replace_existing=True ) # Configure license expiration job - runs daily at midnight scheduler.add_job( deactivate_expired_licenses, 'cron', hour=0, minute=0, id='license_expiration_check', replace_existing=True ) scheduler.start() logging.info(f"Scheduler started. Daily backup scheduled at {config.SCHEDULER_CONFIG['backup_hour']:02d}:{config.SCHEDULER_CONFIG['backup_minute']:02d}") logging.info("Session cleanup job scheduled to run every 60 seconds") logging.info("License expiration check scheduled to run daily at midnight") return scheduler